Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE

This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.

FPIIM-449

Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/test/bot_default.gyp b/test/bot_default.gyp
index ccdf42a..9b39f58 100644
--- a/test/bot_default.gyp
+++ b/test/bot_default.gyp
@@ -11,6 +11,7 @@
           'type': 'none',
           'dependencies': [
             'cctest/cctest.gyp:cctest_run',
+            'fuzzer/fuzzer.gyp:fuzzer_run',
             'intl/intl.gyp:intl_run',
             'message/message.gyp:message_run',
             'mjsunit/mjsunit.gyp:mjsunit_run',
diff --git a/test/bot_default.isolate b/test/bot_default.isolate
index 3277358..d6e4aa3 100644
--- a/test/bot_default.isolate
+++ b/test/bot_default.isolate
@@ -2,8 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 {
+  'variables': {
+    'command': [
+      '../tools/run-tests.py',
+    ],
+  },
   'includes': [
     'cctest/cctest.isolate',
+    'fuzzer/fuzzer.isolate',
     'intl/intl.isolate',
     'message/message.isolate',
     'mjsunit/mjsunit.isolate',
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 9ef2d9b..3b76ce1 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -81,7 +81,6 @@
         'compiler/test-run-jsops.cc',
         'compiler/test-run-machops.cc',
         'compiler/test-run-native-calls.cc',
-        'compiler/test-run-properties.cc',
         'compiler/test-run-stackcheck.cc',
         'compiler/test-run-stubs.cc',
         'compiler/test-run-variables.cc',
@@ -91,6 +90,8 @@
         'expression-type-collector.h',
         'interpreter/test-bytecode-generator.cc',
         'interpreter/test-interpreter.cc',
+        'interpreter/bytecode-expectations-printer.cc',
+        'interpreter/bytecode-expectations-printer.h',
         'gay-fixed.cc',
         'gay-precision.cc',
         'gay-shortest.cc',
@@ -344,12 +345,35 @@
         }
       ],
     },
+    {
+      'target_name': 'generate-bytecode-expectations',
+      'type': 'executable',
+      'dependencies': [
+        '../../tools/gyp/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': ['../../tools/gyp/v8.gyp:v8'],
+        }],
+      ],
+      'include_dirs+': [
+        '../..',
+      ],
+      'sources': [
+        'interpreter/bytecode-expectations-printer.cc',
+        'interpreter/bytecode-expectations-printer.h',
+        'interpreter/generate-bytecode-expectations.cc',
+      ],
+    },
   ],
   'conditions': [
     ['test_isolation_mode != "noop"', {
       'targets': [
         {
-          'target_name': 'cctest_run',
+          'target_name': 'cctest_exe_run',
           'type': 'none',
           'dependencies': [
             'cctest',
@@ -358,6 +382,19 @@
             '../../build/isolate.gypi',
           ],
           'sources': [
+            'cctest_exe.isolate',
+          ],
+        },
+        {
+          'target_name': 'cctest_run',
+          'type': 'none',
+          'dependencies': [
+            'cctest_exe_run',
+          ],
+          'includes': [
+            '../../build/isolate.gypi',
+          ],
+          'sources': [
             'cctest.isolate',
           ],
         },
diff --git a/test/cctest/cctest.isolate b/test/cctest/cctest.isolate
index aee8d83..ab55466 100644
--- a/test/cctest/cctest.isolate
+++ b/test/cctest/cctest.isolate
@@ -4,13 +4,12 @@
 {
   'variables': {
     'files': [
-      '<(PRODUCT_DIR)/cctest<(EXECUTABLE_SUFFIX)',
       './cctest.status',
       './testcfg.py',
     ],
   },
   'includes': [
-    '../../src/base.isolate',
+    'cctest_exe.isolate',
     '../../tools/testrunner/testrunner.isolate',
   ],
-}
\ No newline at end of file
+}
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 8083753..8eaa951 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -71,20 +71,9 @@
   # This tests API threading, no point in running several variants.
   'test-api/Threading*': [PASS, NO_VARIANTS],
 
-  # The cpu profiler tests are notoriously flaky.
-  # BUG(2999). (test/cpu-profiler/CollectCpuProfile)
-  # BUG(3287). (test-cpu-profiler/SampleWhenFrameIsNotSetup)
-  'test-cpu-profiler/CollectCpuProfile': [SKIP],
-  'test-cpu-profiler/CollectCpuProfileSamples': [SKIP],
-  'test-cpu-profiler/FunctionApplySample': [SKIP],
-  'test-cpu-profiler/FunctionCallSample': [SKIP],
-  'test-cpu-profiler/SampleWhenFrameIsNotSetup': [SKIP],
-  'test-cpu-profiler/HotDeoptNoFrameEntry': [SKIP],
-  'test-cpu-profiler/BoundFunctionCall': [SKIP],
+  # BUG(2999). The cpu profiler tests are notoriously flaky.
   'test-cpu-profiler/CpuProfileDeepStack': [SKIP],
-  'test-cpu-profiler/JsNativeJsSample': [SKIP],
-  'test-cpu-profiler/JsNativeJsRuntimeJsSample': [SKIP],
-  'test-cpu-profiler/JsNative1JsNative2JsSample': [SKIP],
+  'test-cpu-profiler/HotDeoptNoFrameEntry': [SKIP],
 
   # BUG(3525). Test crashes flakily.
   'test-debug/RecursiveBreakpoints': [PASS, FLAKY],
@@ -100,6 +89,10 @@
   'test-func-name-inference/UpperCaseClass': [FAIL],
   'test-func-name-inference/LowerCaseClass': [FAIL],
 
+  # BUG(3956). Strong mode is being deprecated. Decide about these tests.
+  'test-api/StrongModeAccessCheckAllowed': [FAIL],
+  'test-api/StrongModeAccessCheckBlocked': [FAIL],
+
   ##############################################################################
   # TurboFan compiler failures.
 
@@ -256,8 +249,11 @@
 ##############################################################################
 ['byteorder == big', {
   # TODO(mips-team): Fix Wasm for big-endian.
+  'test-run-wasm-module/Run_WasmModule_CallAdd': [SKIP],
   'test-run-wasm-module/Run_WasmModule_CallAdd_rev': [SKIP],
+  'test-run-wasm-module/Run_WasmModule_CallMain_recursive': [SKIP],
   'test-run-wasm-module/Run_WasmModule_ReadLoadedDataSegment': [SKIP],
+  '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_WasmInt32*': [SKIP],
@@ -271,6 +267,12 @@
   'test-run-wasm/Run_Wasm_LoadStoreI64_sx': [SKIP],
   'test-run-wasm/Run_WASM_Int64DivS_byzero_const': [SKIP],
   'test-run-wasm/Run_TestI64WasmRunner': [SKIP],
+  'test-run-wasm-js/Run_JSSelect_1': [SKIP],
+  'test-run-wasm-js/Run_JSSelect_2': [SKIP],
+  'test-run-wasm-js/Run_JSSelect_3': [SKIP],
+  'test-run-wasm-js/Run_JSSelect_4': [SKIP],
+  'test-run-wasm-js/Run_JSSelect_5': [SKIP],
+  'test-run-wasm-js/Run_JSSelect_6': [SKIP],
 }],  # 'byteorder == big'
 
 ##############################################################################
@@ -497,93 +499,120 @@
 }],  # 'arch == ppc64 and simulator_run == True'
 
 ['ignition == True', {
-  'test-api/*' : [SKIP],
-  'test-cpu-profiler/*' : [SKIP],
-  'test-debug/*' : [SKIP],
-  'test-func-name-inference/*' : [SKIP],
-  'test-inobject-slack-tracking/*' : [SKIP],
-  'test-run-jsexceptions/*' : [SKIP],
-  'test-serialize/*' : [SKIP],
+  # TODO(yangguo,4690): Test failures in debugger tests.
+  'test-debug/DebugStepLocals': [FAIL],
+  'test-debug/DebugStepKeyedLoadLoop': [FAIL],
+  'test-debug/DebugStepKeyedStoreLoop': [FAIL],
+  'test-debug/DebugStepIf': [FAIL],
+  'test-debug/DebugStepNamedLoadLoop': [FAIL],
+  'test-debug/DebugStepDeclarations': [FAIL],
+  'test-debug/BreakPointConstructCallWithGC': [PASS, FAIL],
+  'test-debug/DebugStepNamedStoreLoop': [FAIL],
+  'test-debug/DebugStepLinearMixedICs': [FAIL],
+  'test-debug/DebugStepSwitch': [FAIL],
+  'test-debug/DebugStepWhile': [FAIL],
+  'test-debug/DebugStepFor': [FAIL],
+  'test-debug/DebugStepForContinue': [FAIL],
+  'test-debug/DebugStepForIn': [FAIL],
+  'test-debug/DebugStepDoWhile': [FAIL],
+  'test-debug/DebugConditional': [FAIL],
+  'test-debug/DebugStepForBreak': [FAIL],
+  'test-debug/DebugStepWith': [FAIL],
+  'test-debug/DebugStepFunctionApply': [FAIL],
+  'test-debug/StepInOutBranch': [FAIL],
+  'test-debug/DebugStepFunctionCall': [FAIL],
 
-  'test-api-interceptors/InterceptorCallICInvalidatedConstantFunctionViaGlobal': [SKIP],
-  'test-api-interceptors/InterceptorLoadICInvalidatedCallbackViaGlobal': [SKIP],
-  'test-api-interceptors/InterceptorLoadICInvalidatedFieldViaGlobal': [SKIP],
-  'test-bytecode-generator/TryCatch': [SKIP],
-  'test-bytecode-generator/TryFinally': [SKIP],
-  'test-compiler/C2JSFrames': [SKIP],
-  'test-compiler/FeedbackVectorPreservedAcrossRecompiles': [SKIP],
-  'test-compiler/FeedbackVectorUnaffectedByScopeChanges': [SKIP],
-  'test-compiler/OptimizedCodeSharing2': [SKIP],
-  'test-compiler/OptimizedCodeSharing3': [SKIP],
-  'test-compiler/Print': [SKIP],
-  'test-compiler/UncaughtThrow': [SKIP],
-  'test-decls/CrossScriptDynamicLookup': [SKIP],
-  'test-decls/Regress425510': [SKIP],
-  'test-feedback-vector/VectorCallICStates': [SKIP],
-  'test-heap/AddInstructionChangesNewSpacePromotion': [SKIP],
-  'test-heap/ArrayShiftSweeping': [SKIP],
-  'test-heap/CanonicalSharedFunctionInfo': [SKIP],
-  'test-heap/CellsInOptimizedCodeAreWeak': [SKIP],
-  'test-heap/CompilationCacheCachingBehavior': [SKIP],
-  'test-heap/CountForcedGC': [SKIP],
-  'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [SKIP],
-  'test-heap/IncrementalMarkingPreservesMonomorphicCallIC': [SKIP],
-  'test-heap/IncrementalMarkingPreservesMonomorphicConstructor': [SKIP],
-  'test-heap/NoWeakHashTableLeakWithIncrementalMarking': [SKIP],
-  'test-heap-profiler/HeapSnapshotCollection': [SKIP],
-  'test-heap-profiler/HeapSnapshotSimd': [SKIP],
-  'test-heap-profiler/HeapSnapshotWeakCollection': [SKIP],
-  'test-heap/OptimizedAllocationAlwaysInNewSpace': [SKIP],
-  'test-heap/PromotionQueue': [SKIP],
-  'test-heap/Regress169209': [SKIP],
-  'test-heap/Regress1878': [SKIP],
-  'test-heap/Regress357137': [SKIP],
-  'test-heap/Regress3631': [SKIP],
-  'test-heap/Regress388880': [SKIP],
-  'test-heap/TestCodeFlushingIncrementalAbort': [SKIP],
-  'test-heap/TestCodeFlushingIncrementalScavenge': [SKIP],
-  'test-heap/TestCodeFlushingIncremental': [SKIP],
-  'test-heap/TestCodeFlushingPreAged': [SKIP],
-  'test-heap/TestCodeFlushing': [SKIP],
-  'test-heap/WeakFunctionInConstructor': [SKIP],
-  'test-log-stack-tracer/CFromJSStackTrace': [SKIP],
-  'test-log-stack-tracer/JsEntrySp': [SKIP],
-  'test-log-stack-tracer/PureCStackTrace': [SKIP],
-  'test-log-stack-tracer/PureJSStackTrace': [SKIP],
-  'test-parsing/DestructuringNegativeTests': [SKIP],
-  'test-parsing/StrongModeFreeVariablesDeclaredByLanguage': [SKIP],
-  'test-parsing/StrongModeFreeVariablesDeclaredByPreviousScript': [SKIP],
-  'test-parsing/StrongModeFreeVariablesDeclaredInGlobalPrototype': [SKIP],
-  'test-pipeline/PipelineGeneric': [SKIP],
-  'test-pipeline/PipelineTyped': [SKIP],
-  'test-profile-generator/BailoutReason': [SKIP],
-  'test-profile-generator/LineNumber': [SKIP],
-  'test-profile-generator/ProfileNodeScriptId': [SKIP],
-  'test-profile-generator/RecordStackTraceAtStartProfiling': [SKIP],
-  'test-run-inlining/InlineTwice': [SKIP],
-  'test-run-jsbranches/ForOfContinueStatement': [SKIP],
-  'test-run-jscalls/LookupCall': [SKIP],
-  'test-run-jsobjects/ArgumentsRest': [SKIP],
-  'test-run-jsops/ClassLiteral': [SKIP],
-  'test-run-jsops/LookupLoad': [SKIP],
-  'test-run-jsops/LookupStore': [SKIP],
-  'test-run-variables/ContextInitializeVariables': [SKIP],
-  'test-run-variables/ContextLoadVariables': [SKIP],
-  'test-run-variables/ContextStoreVariables': [SKIP],
-  'test-run-variables/StackInitializeVariables': [SKIP],
-  'test-run-variables/StackLoadVariables': [SKIP],
-  'test-run-variables/StackStoreVariables': [SKIP],
-  'test-sampler-api/StackFramesConsistent': [SKIP],
-  'test-thread-termination/TerminateCancelTerminateFromThreadItself': [SKIP],
-  'test-thread-termination/TerminateFromOtherThreadWhileMicrotaskRunning': [SKIP],
-  'test-thread-termination/TerminateOnlyV8ThreadFromThreadItselfNoLoop': [SKIP],
-  'test-thread-termination/TerminationInInnerTryCall': [SKIP],
-  'test-unscopables-hidden-prototype/Unscopables': [SKIP],
+  # TODO(yangguo,4690): Required DebuggerStatement support.
+  'test-profile-generator/BailoutReason': [FAIL],
+
+  # TODO(rmcilroy,4680): Check failed: toplevel_test_code_event_found.
+  'test-serialize/SerializeToplevelIsolates': [FAIL],
+
+  # BUG(4333). Function name inferrer does not work for ES6 clases.
+  'test-func-name-inference/UpperCaseClass': [TIMEOUT],
+  'test-func-name-inference/LowerCaseClass': [TIMEOUT],
+
+  # TODO(rmcilroy,4681): Requires support for generators.
+  'test-inobject-slack-tracking/JSGeneratorObjectBasic': [FAIL],
+  'test-inobject-slack-tracking/JSGeneratorObjectBasicNoInlineNew': [FAIL],
+  'test-api/IsGeneratorFunctionOrObject': [FAIL],
+
+  # TODO(rmcilroy,4680): Strong mode failures.
+  'test-api/AccessorShouldThrowOnError': [FAIL],
+  'test-api/InterceptorShouldThrowOnError': [FAIL],
+
+  # TODO(rmcilroy,4680): The function_data field should be a BytecodeArray on interpreter entry
+  'test-api/SetFunctionEntryHook': [FAIL],
+
+  # TODO(rmcilroy,4680): Fail on shared_function_data()->IsUndefined in
+  #compiler.cc
+  'test-heap/CanonicalSharedFunctionInfo': [PASS, ['mode == debug or dcheck_always_on == True', FAIL]],
+
+  # TODO(rmcilroy,4680): 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,4680): Check failed: fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft().
+  'test-compiler/OptimizedCodeSharing2': [FAIL],
+  'test-compiler/OptimizedCodeSharing3': [FAIL],
+
+  # TODO(rmcilroy,4689): Stack trace line number failures.
+  'test-run-jsexceptions/ThrowMessagePosition': [FAIL],
+  'test-api/TryCatchMixedNesting': [FAIL],
+
+  # TODO(rmcilroy,4680): Test assert errors.
+  'test-cpu-profiler/CodeEvents': [FAIL],
+  'test-cpu-profiler/TickEvents': [FAIL],
+  'test-cpu-profiler/BoundFunctionCall': [FAIL],
+  'test-cpu-profiler/CollectCpuProfile': [FAIL],
+  'test-cpu-profiler/CollectSampleAPI': [FAIL],
+  'test-cpu-profiler/CpuProfileDeepStack': [FAIL],
+  'test-cpu-profiler/FunctionApplySample': [FAIL],
+  'test-cpu-profiler/FunctionCallSample': [FAIL],
+  'test-cpu-profiler/FunctionDetails': [FAIL],
+  'test-cpu-profiler/HotDeoptNoFrameEntry': [FAIL],
+  'test-cpu-profiler/JsNative1JsNative2JsSample': [FAIL],
+  'test-cpu-profiler/JsNativeJsRuntimeJsSample': [FAIL],
+  'test-cpu-profiler/JsNativeJsRuntimeJsSampleMultiple': [FAIL],
+  'test-cpu-profiler/JsNativeJsSample': [FAIL],
+  'test-cpu-profiler/NativeMethodUninitializedIC': [FAIL],
+  'test-cpu-profiler/NativeMethodMonomorphicIC': [FAIL],
+  'test-cpu-profiler/NativeAccessorUninitializedIC': [FAIL],
+  'test-cpu-profiler/NativeAccessorMonomorphicIC': [FAIL],
+  'test-cpu-profiler/SampleWhenFrameIsNotSetup': [FAIL],
+  'test-sampler-api/StackFramesConsistent': [FAIL],
+  'test-profile-generator/LineNumber': [FAIL],
+  'test-profile-generator/ProfileNodeScriptId': [FAIL],
+  'test-profile-generator/RecordStackTraceAtStartProfiling': [FAIL],
+  'test-feedback-vector/VectorCallICStates': [FAIL],
+  'test-compiler/FeedbackVectorPreservedAcrossRecompiles': [FAIL],
+  'test-api/PromiseRejectCallback': [FAIL],
+  'test-api/SetJitCodeEventHandler': [FAIL],
+  'test-heap/WeakFunctionInConstructor': [FAIL],
+  'test-heap/Regress169209': [FAIL],
+  'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [FAIL],
+  'test-heap/IncrementalMarkingPreservesMonomorphicConstructor': [FAIL],
+  'test-heap/IncrementalMarkingPreservesMonomorphicCallIC': [FAIL],
+  'test-heap/CompilationCacheCachingBehavior': [FAIL],
+  'test-heap/CellsInOptimizedCodeAreWeak': [FAIL],
+  'test-run-inlining/InlineTwice': [FAIL],
+  'test-serialize/SerializeInternalReference': [FAIL, ['arch == arm or arch == arm64', PASS]],
 }],  # ignition == True
 
-['ignition == True and arch == arm64', {
-  'test-js-arm64-variables/lookup_slots': [SKIP],
-  'test-spaces/SizeOfFirstPageIsLargeEnough': [SKIP],
-}],  # ignition == True and arch == arm64
+['ignition == True and arch == x64', {
+  # TODO(rmcilroy,4680): The function_data field should be a BytecodeArray on interpreter entry
+  'test-serialize/PerIsolateSnapshotBlobsOutdatedContextWithOverflow': [PASS, ['mode == debug', FAIL]],
+  'test-serialize/PerIsolateSnapshotBlobsWithLocker': [PASS, ['mode == debug', FAIL]],
+  'test-serialize/SnapshotBlobsStackOverflow': [PASS, ['mode == debug', FAIL]],
+  'test-serialize/PerIsolateSnapshotBlobs': [PASS, ['mode == debug', FAIL]],
+  'test-serialize/SerializationMemoryStats': [PASS, ['mode == debug', FAIL]],
+
+  # TODO(rmcilroy,4680): Test assert errors.
+  'test-heap-profiler/HeapSnapshotSimd': [PASS, ['mode == debug', FAIL]],
+  'test-api/InitializeDefaultIsolateOnSecondaryThread1': [PASS, ['mode == debug', FAIL]],
+}],
 
 ]
diff --git a/test/cctest/cctest_exe.isolate b/test/cctest/cctest_exe.isolate
new file mode 100644
index 0000000..da53278
--- /dev/null
+++ b/test/cctest/cctest_exe.isolate
@@ -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.
+{
+  'variables': {
+    'files': [
+      '<(PRODUCT_DIR)/cctest<(EXECUTABLE_SUFFIX)',
+    ],
+  },
+  'includes': [
+    '../../src/base.isolate',
+  ],
+}
diff --git a/test/cctest/compiler/c-signature.h b/test/cctest/compiler/c-signature.h
index 13ef38a..1c2f963 100644
--- a/test/cctest/compiler/c-signature.h
+++ b/test/cctest/compiler/c-signature.h
@@ -53,16 +53,16 @@
  public:
   template <typename P1 = void, typename P2 = void, typename P3 = void,
             typename P4 = void, typename P5 = void>
-  void VerifyParams() {
+  static void VerifyParams(MachineSignature* sig) {
     // Verifies the C signature against the machine types. Maximum {5} params.
-    CHECK_LT(parameter_count(), 6u);
+    CHECK_LT(sig->parameter_count(), 6u);
     const int kMax = 5;
     MachineType params[] = {MachineTypeForC<P1>(), MachineTypeForC<P2>(),
                             MachineTypeForC<P3>(), MachineTypeForC<P4>(),
                             MachineTypeForC<P5>()};
     for (int p = kMax - 1; p >= 0; p--) {
-      if (p < static_cast<int>(parameter_count())) {
-        CHECK_EQ(GetParam(p), params[p]);
+      if (p < static_cast<int>(sig->parameter_count())) {
+        CHECK_EQ(sig->GetParam(p), params[p]);
       } else {
         CHECK_EQ(MachineType::None(), params[p]);
       }
diff --git a/test/cctest/compiler/call-tester.h b/test/cctest/compiler/call-tester.h
index e60f717..8ee6b99 100644
--- a/test/cctest/compiler/call-tester.h
+++ b/test/cctest/compiler/call-tester.h
@@ -119,7 +119,7 @@
 template <typename R>
 class CallHelper {
  public:
-  explicit CallHelper(Isolate* isolate, CSignature* csig)
+  explicit CallHelper(Isolate* isolate, MachineSignature* csig)
       : csig_(csig), isolate_(isolate) {
     USE(isolate_);
   }
@@ -127,47 +127,47 @@
 
   R Call() {
     typedef R V8_CDECL FType();
-    csig_->VerifyParams();
+    CSignature::VerifyParams(csig_);
     return DoCall(FUNCTION_CAST<FType*>(Generate()));
   }
 
   template <typename P1>
   R Call(P1 p1) {
     typedef R V8_CDECL FType(P1);
-    csig_->VerifyParams<P1>();
+    CSignature::VerifyParams<P1>(csig_);
     return DoCall(FUNCTION_CAST<FType*>(Generate()), p1);
   }
 
   template <typename P1, typename P2>
   R Call(P1 p1, P2 p2) {
     typedef R V8_CDECL FType(P1, P2);
-    csig_->VerifyParams<P1, P2>();
+    CSignature::VerifyParams<P1, P2>(csig_);
     return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2);
   }
 
   template <typename P1, typename P2, typename P3>
   R Call(P1 p1, P2 p2, P3 p3) {
     typedef R V8_CDECL FType(P1, P2, P3);
-    csig_->VerifyParams<P1, P2, P3>();
+    CSignature::VerifyParams<P1, P2, P3>(csig_);
     return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
   }
 
   template <typename P1, typename P2, typename P3, typename P4>
   R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
     typedef R V8_CDECL FType(P1, P2, P3, P4);
-    csig_->VerifyParams<P1, P2, P3, P4>();
+    CSignature::VerifyParams<P1, P2, P3, P4>(csig_);
     return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
   }
 
   template <typename P1, typename P2, typename P3, typename P4, typename P5>
   R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
     typedef R V8_CDECL FType(P1, P2, P3, P4, P5);
-    csig_->VerifyParams<P1, P2, P3, P4, P5>();
+    CSignature::VerifyParams<P1, P2, P3, P4, P5>(csig_);
     return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4, p5);
   }
 
  protected:
-  CSignature* csig_;
+  MachineSignature* csig_;
 
   virtual byte* Generate() = 0;
 
@@ -342,7 +342,7 @@
 template <typename T>
 class CodeRunner : public CallHelper<T> {
  public:
-  CodeRunner(Isolate* isolate, Handle<Code> code, CSignature* csig)
+  CodeRunner(Isolate* isolate, Handle<Code> code, MachineSignature* csig)
       : CallHelper<T>(isolate, csig), code_(code) {}
   virtual ~CodeRunner() {}
 
diff --git a/test/cctest/compiler/codegen-tester.h b/test/cctest/compiler/codegen-tester.h
index 56e90c6..5d670bf 100644
--- a/test/cctest/compiler/codegen-tester.h
+++ b/test/cctest/compiler/codegen-tester.h
@@ -35,10 +35,13 @@
             Linkage::GetSimplifiedCDescriptor(
                 main_zone(),
                 CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0,
-                                p1, p2, p3, p4)),
+                                p1, p2, p3, p4),
+                true),
             MachineType::PointerRepresentation(),
             InstructionSelector::SupportedMachineOperatorFlags()) {}
 
+  virtual ~RawMachineAssemblerTester() {}
+
   void CheckNumber(double expected, Object* number) {
     CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
   }
@@ -85,6 +88,7 @@
       : BufferedRawMachineAssemblerTester(ComputeParameterCount(p0, p1, p2, p3),
                                           p0, p1, p2, p3) {}
 
+  virtual byte* Generate() { return RawMachineAssemblerTester::Generate(); }
 
   // The BufferedRawMachineAssemblerTester does not pass parameters directly
   // to the constructed IR graph. Instead it passes a pointer to the parameter
@@ -92,11 +96,10 @@
   // 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];
   }
 
-
   // The BufferedRawMachineAssemblerTester adds a Store node to the IR graph
   // to store the graph's return value in memory. The memory address for the
   // Store node is provided as a parameter. By storing the return value in
@@ -110,7 +113,7 @@
 
   ReturnType Call() {
     ReturnType return_value;
-    test_graph_signature_->VerifyParams();
+    CSignature::VerifyParams(test_graph_signature_);
     CallHelper<int32_t>::Call(reinterpret_cast<void*>(&return_value));
     return return_value;
   }
@@ -118,7 +121,7 @@
   template <typename P0>
   ReturnType Call(P0 p0) {
     ReturnType return_value;
-    test_graph_signature_->VerifyParams<P0>();
+    CSignature::VerifyParams<P0>(test_graph_signature_);
     CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
                               reinterpret_cast<void*>(&return_value));
     return return_value;
@@ -127,7 +130,7 @@
   template <typename P0, typename P1>
   ReturnType Call(P0 p0, P1 p1) {
     ReturnType return_value;
-    test_graph_signature_->VerifyParams<P0, P1>();
+    CSignature::VerifyParams<P0, P1>(test_graph_signature_);
     CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
                               reinterpret_cast<void*>(&p1),
                               reinterpret_cast<void*>(&return_value));
@@ -137,7 +140,7 @@
   template <typename P0, typename P1, typename P2>
   ReturnType Call(P0 p0, P1 p1, P2 p2) {
     ReturnType return_value;
-    test_graph_signature_->VerifyParams<P0, P1, P2>();
+    CSignature::VerifyParams<P0, P1, P2>(test_graph_signature_);
     CallHelper<int32_t>::Call(
         reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
         reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&return_value));
@@ -147,7 +150,7 @@
   template <typename P0, typename P1, typename P2, typename P3>
   ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
     ReturnType return_value;
-    test_graph_signature_->VerifyParams<P0, P1, P2, P3>();
+    CSignature::VerifyParams<P0, P1, P2, P3>(test_graph_signature_);
     CallHelper<int32_t>::Call(
         reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
         reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3),
@@ -245,6 +248,7 @@
                               : Load(p3, RawMachineAssembler::Parameter(3));
   }
 
+  virtual byte* Generate() { return RawMachineAssemblerTester::Generate(); }
 
   // The BufferedRawMachineAssemblerTester does not pass parameters directly
   // to the constructed IR graph. Instead it passes a pointer to the parameter
@@ -258,26 +262,26 @@
 
 
   void Call() {
-    test_graph_signature_->VerifyParams();
+    CSignature::VerifyParams(test_graph_signature_);
     CallHelper<void>::Call();
   }
 
   template <typename P0>
   void Call(P0 p0) {
-    test_graph_signature_->VerifyParams<P0>();
+    CSignature::VerifyParams<P0>(test_graph_signature_);
     CallHelper<void>::Call(reinterpret_cast<void*>(&p0));
   }
 
   template <typename P0, typename P1>
   void Call(P0 p0, P1 p1) {
-    test_graph_signature_->VerifyParams<P0, P1>();
+    CSignature::VerifyParams<P0, P1>(test_graph_signature_);
     CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
                            reinterpret_cast<void*>(&p1));
   }
 
   template <typename P0, typename P1, typename P2>
   void Call(P0 p0, P1 p1, P2 p2) {
-    test_graph_signature_->VerifyParams<P0, P1, P2>();
+    CSignature::VerifyParams<P0, P1, P2>(test_graph_signature_);
     CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
                            reinterpret_cast<void*>(&p1),
                            reinterpret_cast<void*>(&p2));
@@ -285,7 +289,7 @@
 
   template <typename P0, typename P1, typename P2, typename P3>
   void Call(P0 p0, P1 p1, P2 p2, P3 p3) {
-    test_graph_signature_->VerifyParams<P0, P1, P2, P3>();
+    CSignature::VerifyParams<P0, P1, P2, P3>(test_graph_signature_);
     CallHelper<void>::Call(
         reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
         reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3));
@@ -397,7 +401,6 @@
 
 // A helper class for testing code sequences that take two float parameters and
 // return a float value.
-// TODO(titzer): figure out how to return floats correctly on ia32.
 class Float32BinopTester : public BinopTester<float, USE_RESULT_BUFFER> {
  public:
   explicit Float32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
@@ -407,7 +410,6 @@
 
 // A helper class for testing code sequences that take two double parameters and
 // return a double value.
-// TODO(titzer): figure out how to return doubles correctly on ia32.
 class Float64BinopTester : public BinopTester<double, USE_RESULT_BUFFER> {
  public:
   explicit Float64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
@@ -524,7 +526,8 @@
 // and run the generated code to ensure it produces the correct results.
 class Int32BinopInputShapeTester {
  public:
-  explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g) : gen(g) {}
+  explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g)
+      : gen(g), input_a(0), input_b(0) {}
 
   void TestAllInputShapes();
 
@@ -537,24 +540,6 @@
   void RunLeft(RawMachineAssemblerTester<int32_t>* m);
   void RunRight(RawMachineAssemblerTester<int32_t>* m);
 };
-
-// TODO(bmeurer): Drop this crap once we switch to GTest/Gmock.
-static inline void CheckFloatEq(volatile float x, volatile float y) {
-  if (std::isnan(x)) {
-    CHECK(std::isnan(y));
-  } else {
-    CHECK_EQ(x, y);
-  }
-}
-
-static inline void CheckDoubleEq(volatile double x, volatile double y) {
-  if (std::isnan(x)) {
-    CHECK(std::isnan(y));
-  } else {
-    CHECK_EQ(x, y);
-  }
-}
-
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/compiler/function-tester.h b/test/cctest/compiler/function-tester.h
index 2fcd353..c6093ce 100644
--- a/test/cctest/compiler/function-tester.h
+++ b/test/cctest/compiler/function-tester.h
@@ -162,15 +162,26 @@
 
   Handle<Object> false_value() { return isolate->factory()->false_value(); }
 
+  static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) {
+    JSFunction* p = NULL;
+    {  // because of the implicit handle scope of FunctionTester.
+      FunctionTester f(graph, param_count);
+      p = *f.function;
+    }
+    return Handle<JSFunction>(p);  // allocated in outer handle scope.
+  }
+
+ private:
+  uint32_t flags_;
+
   Handle<JSFunction> Compile(Handle<JSFunction> function) {
-// TODO(titzer): make this method private.
     Zone zone;
     ParseInfo parse_info(&zone, function);
     CompilationInfo info(&parse_info);
     info.MarkAsDeoptimizationEnabled();
 
     CHECK(Parser::ParseStatic(info.parse_info()));
-    info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
+    info.SetOptimizing();
     if (flags_ & CompilationInfo::kFunctionContextSpecializing) {
       info.MarkAsFunctionContextSpecializing();
     }
@@ -192,26 +203,13 @@
     return function;
   }
 
-  static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) {
-    JSFunction* p = NULL;
-    {  // because of the implicit handle scope of FunctionTester.
-      FunctionTester f(graph, param_count);
-      p = *f.function;
-    }
-    return Handle<JSFunction>(p);  // allocated in outer handle scope.
-  }
-
- private:
-  uint32_t flags_;
-
   std::string BuildFunction(int param_count) {
     std::string function_string = "(function(";
     if (param_count > 0) {
-      char next = 'a';
-      function_string += next;
-      while (param_count-- > 0) {
+      function_string += 'a';
+      for (int i = 1; i < param_count; i++) {
         function_string += ',';
-        function_string += ++next;
+        function_string += static_cast<char>('a' + i);
       }
     }
     function_string += "){})";
@@ -231,8 +229,7 @@
     CompilationInfo info(&parse_info);
 
     CHECK(Parser::ParseStatic(info.parse_info()));
-    info.SetOptimizing(BailoutId::None(),
-                       Handle<Code>(function->shared()->code()));
+    info.SetOptimizing();
     CHECK(Compiler::Analyze(info.parse_info()));
     CHECK(Compiler::EnsureDeoptimizationSupport(&info));
 
diff --git a/test/cctest/compiler/test-code-stub-assembler.cc b/test/cctest/compiler/test-code-stub-assembler.cc
index d7a7a81..0306561 100644
--- a/test/cctest/compiler/test-code-stub-assembler.cc
+++ b/test/cctest/compiler/test-code-stub-assembler.cc
@@ -16,7 +16,7 @@
   CodeStubAssemblerTester(Isolate* isolate,
                           const CallInterfaceDescriptor& descriptor)
       : CodeStubAssembler(isolate, isolate->runtime_zone(), descriptor,
-                          Code::STUB, "test"),
+                          Code::ComputeFlags(Code::STUB), "test"),
         scope_(isolate) {}
 
  private:
@@ -120,6 +120,133 @@
   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());
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/compiler/test-js-context-specialization.cc b/test/cctest/compiler/test-js-context-specialization.cc
index 43b7665..c7cd47a 100644
--- a/test/cctest/compiler/test-js-context-specialization.cc
+++ b/test/cctest/compiler/test-js-context-specialization.cc
@@ -225,8 +225,8 @@
         t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), other_load);
 
     Node* add = t.graph()->NewNode(
-        t.javascript()->Add(LanguageMode::SLOPPY, BinaryOperationHints::Any()),
-        value_use, other_use, param_context, t.jsgraph()->EmptyFrameState(),
+        t.javascript()->Add(BinaryOperationHints::Any()), value_use, other_use,
+        param_context, t.jsgraph()->EmptyFrameState(),
         t.jsgraph()->EmptyFrameState(), other_load, start);
 
     Node* ret =
diff --git a/test/cctest/compiler/test-js-typed-lowering.cc b/test/cctest/compiler/test-js-typed-lowering.cc
index c8b7734..24db6a5 100644
--- a/test/cctest/compiler/test-js-typed-lowering.cc
+++ b/test/cctest/compiler/test-js-typed-lowering.cc
@@ -17,19 +17,6 @@
 namespace internal {
 namespace compiler {
 
-#ifndef TEST_WITH_STRONG
-#define TEST_WITH_STRONG(Name)                                                 \
-  static void Test##Name();                                                    \
-  static void TestWithStrong##Name(LanguageMode language_mode);                \
-  CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true, true);  \
-  static void Test##Name() {                                                   \
-    TestWithStrong##Name(LanguageMode::SLOPPY);                                \
-    TestWithStrong##Name(LanguageMode::STRONG);                                \
-  }                                                                            \
-  static void TestWithStrong##Name(LanguageMode language_mode)
-#endif
-
-
 class JSTypedLoweringTester : public HandleAndZoneScope {
  public:
   explicit JSTypedLoweringTester(int num_parameters = 0)
@@ -163,17 +150,8 @@
   }
 
   Node* UseForEffect(Node* node) {
-    // TODO(titzer): use EffectPhi after fixing EffectCount
-    if (OperatorProperties::GetFrameStateInputCount(javascript.ToNumber()) >
-        0) {
-      CHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(
-                      javascript.ToNumber()));
-      return graph.NewNode(javascript.ToNumber(), node, context(),
-                           EmptyFrameState(context()), node, control());
-    } else {
-      return graph.NewNode(javascript.ToNumber(), node, context(), node,
-                           control());
-    }
+    Node* merge = graph.NewNode(common.Merge(1), start());
+    return graph.NewNode(common.EffectPhi(1), node, merge);
   }
 
   void CheckEffectInput(Node* effect, Node* use) {
@@ -240,7 +218,7 @@
 
 // TODO(turbofan): Lowering of StringAdd is disabled for now.
 #if 0
-TEST_WITH_STRONG(StringBinops) {
+TEST(StringBinops) {
   JSTypedLoweringTester R;
 
   for (size_t i = 0; i < arraysize(kStringTypes); ++i) {
@@ -249,7 +227,7 @@
     for (size_t j = 0; j < arraysize(kStringTypes); ++j) {
       Node* p1 = R.Parameter(kStringTypes[j], 1);
 
-      Node* add = R.Binop(R.javascript.Add(language_mode), p0, p1);
+      Node* add = R.Binop(R.javascript.Add(), p0, p1);
       Node* r = R.reduce(add);
 
       R.CheckBinop(IrOpcode::kStringAdd, r);
@@ -260,14 +238,12 @@
 }
 #endif
 
-
-TEST_WITH_STRONG(AddNumber1) {
+TEST(AddNumber1) {
   JSTypedLoweringTester R;
   for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
     Node* p0 = R.Parameter(kNumberTypes[i], 0);
     Node* p1 = R.Parameter(kNumberTypes[i], 1);
-    Node* add = R.Binop(
-        R.javascript.Add(language_mode, BinaryOperationHints::Any()), p0, p1);
+    Node* add = R.Binop(R.javascript.Add(BinaryOperationHints::Any()), p0, p1);
     Node* r = R.reduce(add);
 
     R.CheckBinop(IrOpcode::kNumberAdd, r);
@@ -276,20 +252,14 @@
   }
 }
 
-
-TEST_WITH_STRONG(NumberBinops) {
+TEST(NumberBinops) {
   JSTypedLoweringTester R;
   const Operator* ops[] = {
-      R.javascript.Add(language_mode, R.hints),
-      R.simplified.NumberAdd(),
-      R.javascript.Subtract(language_mode, R.hints),
-      R.simplified.NumberSubtract(),
-      R.javascript.Multiply(language_mode, R.hints),
-      R.simplified.NumberMultiply(),
-      R.javascript.Divide(language_mode, R.hints),
-      R.simplified.NumberDivide(),
-      R.javascript.Modulus(language_mode, R.hints),
-      R.simplified.NumberModulus(),
+      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(),
   };
 
   for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
@@ -329,14 +299,13 @@
 // A helper class for testing lowering of bitwise shift operators.
 class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester {
  public:
-  explicit JSBitwiseShiftTypedLoweringTester(LanguageMode language_mode)
-      : JSTypedLoweringTester(), language_mode_(language_mode) {
+  JSBitwiseShiftTypedLoweringTester() : JSTypedLoweringTester() {
     int i = 0;
-    set(i++, javascript.ShiftLeft(language_mode_, hints), true);
+    set(i++, javascript.ShiftLeft(hints), true);
     set(i++, simplified.NumberShiftLeft(), false);
-    set(i++, javascript.ShiftRight(language_mode_, hints), true);
+    set(i++, javascript.ShiftRight(hints), true);
     set(i++, simplified.NumberShiftRight(), false);
-    set(i++, javascript.ShiftRightLogical(language_mode_, hints), false);
+    set(i++, javascript.ShiftRightLogical(hints), false);
     set(i++, simplified.NumberShiftRightLogical(), false);
   }
   static const int kNumberOps = 6;
@@ -344,7 +313,6 @@
   bool signedness[kNumberOps];
 
  private:
-  LanguageMode language_mode_;
   void set(int idx, const Operator* op, bool s) {
     ops[idx] = op;
     signedness[idx] = s;
@@ -353,7 +321,7 @@
 
 
 TEST(Int32BitwiseShifts) {
-  JSBitwiseShiftTypedLoweringTester R(LanguageMode::SLOPPY);
+  JSBitwiseShiftTypedLoweringTester R;
 
   Type* types[] = {
       Type::SignedSmall(), Type::UnsignedSmall(), Type::Negative32(),
@@ -387,14 +355,13 @@
 // A helper class for testing lowering of bitwise operators.
 class JSBitwiseTypedLoweringTester : public JSTypedLoweringTester {
  public:
-  explicit JSBitwiseTypedLoweringTester(LanguageMode language_mode)
-      : JSTypedLoweringTester(), language_mode_(language_mode) {
+  JSBitwiseTypedLoweringTester() : JSTypedLoweringTester() {
     int i = 0;
-    set(i++, javascript.BitwiseOr(language_mode_, hints), true);
+    set(i++, javascript.BitwiseOr(hints), true);
     set(i++, simplified.NumberBitwiseOr(), true);
-    set(i++, javascript.BitwiseXor(language_mode_, hints), true);
+    set(i++, javascript.BitwiseXor(hints), true);
     set(i++, simplified.NumberBitwiseXor(), true);
-    set(i++, javascript.BitwiseAnd(language_mode_, hints), true);
+    set(i++, javascript.BitwiseAnd(hints), true);
     set(i++, simplified.NumberBitwiseAnd(), true);
   }
   static const int kNumberOps = 6;
@@ -402,7 +369,6 @@
   bool signedness[kNumberOps];
 
  private:
-  LanguageMode language_mode_;
   void set(int idx, const Operator* op, bool s) {
     ops[idx] = op;
     signedness[idx] = s;
@@ -411,7 +377,7 @@
 
 
 TEST(Int32BitwiseBinops) {
-  JSBitwiseTypedLoweringTester R(LanguageMode::SLOPPY);
+  JSBitwiseTypedLoweringTester R;
 
   Type* types[] = {
       Type::SignedSmall(),   Type::UnsignedSmall(), Type::Unsigned32(),
@@ -558,7 +524,6 @@
 
   {  // ToString(number)
     Node* r = R.ReduceUnop(op, Type::Number());
-    // TODO(titzer): could remove effects
     CHECK_EQ(IrOpcode::kJSToString, r->opcode());
   }
 
@@ -602,17 +567,14 @@
   }
 }
 
-
-TEST_WITH_STRONG(StringComparison) {
+TEST(StringComparison) {
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.LessThan(language_mode), R.simplified.StringLessThan(),
-      R.javascript.LessThanOrEqual(language_mode),
-      R.simplified.StringLessThanOrEqual(),
-      R.javascript.GreaterThan(language_mode), R.simplified.StringLessThan(),
-      R.javascript.GreaterThanOrEqual(language_mode),
-      R.simplified.StringLessThanOrEqual()};
+      R.javascript.LessThan(),           R.simplified.StringLessThan(),
+      R.javascript.LessThanOrEqual(),    R.simplified.StringLessThanOrEqual(),
+      R.javascript.GreaterThan(),        R.simplified.StringLessThan(),
+      R.javascript.GreaterThanOrEqual(), R.simplified.StringLessThanOrEqual()};
 
   for (size_t i = 0; i < arraysize(kStringTypes); i++) {
     Node* p0 = R.Parameter(kStringTypes[i], 0);
@@ -652,17 +614,14 @@
   }
 }
 
-
-TEST_WITH_STRONG(NumberComparison) {
+TEST(NumberComparison) {
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.LessThan(language_mode), R.simplified.NumberLessThan(),
-      R.javascript.LessThanOrEqual(language_mode),
-      R.simplified.NumberLessThanOrEqual(),
-      R.javascript.GreaterThan(language_mode), R.simplified.NumberLessThan(),
-      R.javascript.GreaterThanOrEqual(language_mode),
-      R.simplified.NumberLessThanOrEqual()};
+      R.javascript.LessThan(),           R.simplified.NumberLessThan(),
+      R.javascript.LessThanOrEqual(),    R.simplified.NumberLessThanOrEqual(),
+      R.javascript.GreaterThan(),        R.simplified.NumberLessThan(),
+      R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual()};
 
   Node* const p0 = R.Parameter(Type::Number(), 0);
   Node* const p1 = R.Parameter(Type::Number(), 1);
@@ -684,8 +643,7 @@
   }
 }
 
-
-TEST_WITH_STRONG(MixedComparison1) {
+TEST(MixedComparison1) {
   JSTypedLoweringTester R;
 
   Type* types[] = {Type::Number(), Type::String(),
@@ -697,16 +655,15 @@
     for (size_t j = 0; j < arraysize(types); j++) {
       Node* p1 = R.Parameter(types[j], 1);
       {
-        const Operator* less_than = R.javascript.LessThan(language_mode);
+        const Operator* less_than = R.javascript.LessThan();
         Node* cmp = R.Binop(less_than, p0, p1);
         Node* r = R.reduce(cmp);
         if (types[i]->Is(Type::String()) && types[j]->Is(Type::String())) {
           R.CheckBinop(R.simplified.StringLessThan(), r);
         } else if ((types[i]->Is(Type::Number()) &&
                     types[j]->Is(Type::Number())) ||
-                   (!is_strong(language_mode) &&
-                    (!types[i]->Maybe(Type::String()) ||
-                     !types[j]->Maybe(Type::String())))) {
+                   (!types[i]->Maybe(Type::String()) ||
+                    !types[j]->Maybe(Type::String()))) {
           R.CheckBinop(R.simplified.NumberLessThan(), r);
         } else {
           // No reduction of mixed types.
@@ -717,8 +674,7 @@
   }
 }
 
-
-TEST_WITH_STRONG(RemoveToNumberEffects) {
+TEST(RemoveToNumberEffects) {
   JSTypedLoweringTester R;
 
   Node* effect_use = NULL;
@@ -744,14 +700,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(language_mode, R.hints),
-                                     ton, ton, R.context(), frame_state,
-                                     frame_state, ton, R.start());
+        effect_use =
+            R.graph.NewNode(R.javascript.Add(R.hints), ton, ton, R.context(),
+                            frame_state, frame_state, ton, R.start());
         break;
       case 4:
-        effect_use = R.graph.NewNode(R.javascript.Add(language_mode, R.hints),
-                                     p0, p0, R.context(), frame_state,
-                                     frame_state, ton, R.start());
+        effect_use =
+            R.graph.NewNode(R.javascript.Add(R.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());
@@ -896,9 +852,16 @@
     Node* p1 = R.Parameter(types[i]);
     CheckEqualityReduction(&R, true, p0, p1, IrOpcode::kReferenceEqual);
   }
-  // TODO(titzer): Equal(RefEqualTypes)
 }
 
+TEST(StrictEqualityForUnique) {
+  JSTypedLoweringTester R;
+
+  Node* p0 = R.Parameter(Type::Unique());
+  Node* p1 = R.Parameter(Type::Unique());
+  CheckEqualityReduction(&R, true, p0, p1, IrOpcode::kReferenceEqual);
+  CheckEqualityReduction(&R, true, p1, p0, IrOpcode::kReferenceEqual);
+}
 
 TEST(StringEquality) {
   JSTypedLoweringTester R;
@@ -909,27 +872,18 @@
   CheckEqualityReduction(&R, false, p0, p1, IrOpcode::kStringEqual);
 }
 
-
-TEST_WITH_STRONG(RemovePureNumberBinopEffects) {
+TEST(RemovePureNumberBinopEffects) {
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.Equal(),
-      R.simplified.NumberEqual(),
-      R.javascript.Add(language_mode, R.hints),
-      R.simplified.NumberAdd(),
-      R.javascript.Subtract(language_mode, R.hints),
-      R.simplified.NumberSubtract(),
-      R.javascript.Multiply(language_mode, R.hints),
-      R.simplified.NumberMultiply(),
-      R.javascript.Divide(language_mode, R.hints),
-      R.simplified.NumberDivide(),
-      R.javascript.Modulus(language_mode, R.hints),
-      R.simplified.NumberModulus(),
-      R.javascript.LessThan(language_mode),
-      R.simplified.NumberLessThan(),
-      R.javascript.LessThanOrEqual(language_mode),
-      R.simplified.NumberLessThanOrEqual(),
+      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(),
   };
 
   for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -950,12 +904,9 @@
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.Subtract(LanguageMode::SLOPPY, R.hints),
-      R.simplified.NumberSubtract(),
-      R.javascript.Multiply(LanguageMode::SLOPPY, R.hints),
-      R.simplified.NumberMultiply(),
-      R.javascript.Divide(LanguageMode::SLOPPY, R.hints),
-      R.simplified.NumberDivide(),
+      R.javascript.Subtract(R.hints), R.simplified.NumberSubtract(),
+      R.javascript.Multiply(R.hints), R.simplified.NumberMultiply(),
+      R.javascript.Divide(R.hints),   R.simplified.NumberDivide(),
   };
 
   for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -978,14 +929,10 @@
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.Add(LanguageMode::SLOPPY, R.hints),
-      R.simplified.NumberAdd(),
-      R.javascript.Subtract(LanguageMode::SLOPPY, R.hints),
-      R.simplified.NumberSubtract(),
-      R.javascript.Multiply(LanguageMode::SLOPPY, R.hints),
-      R.simplified.NumberMultiply(),
-      R.javascript.Divide(LanguageMode::SLOPPY, R.hints),
-      R.simplified.NumberDivide(),
+      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(),
   };
 
   for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -1020,10 +967,8 @@
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.GreaterThan(LanguageMode::SLOPPY),
-      R.simplified.NumberLessThan(),
-      R.javascript.GreaterThanOrEqual(LanguageMode::SLOPPY),
-      R.simplified.NumberLessThanOrEqual(),
+      R.javascript.GreaterThan(), R.simplified.NumberLessThan(),
+      R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
   };
 
   for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -1070,7 +1015,7 @@
 
 
 TEST(Int32BinopEffects) {
-  JSBitwiseTypedLoweringTester R(LanguageMode::SLOPPY);
+  JSBitwiseTypedLoweringTester R;
   for (int j = 0; j < R.kNumberOps; j += 2) {
     bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
     BinopEffectsTester B(R.ops[j], I32Type(signed_left), I32Type(signed_right));
@@ -1150,10 +1095,9 @@
   }
 }
 
-
-TEST_WITH_STRONG(Int32AddNarrowing) {
+TEST(Int32AddNarrowing) {
   {
-    JSBitwiseTypedLoweringTester R(language_mode);
+    JSBitwiseTypedLoweringTester R;
 
     for (int o = 0; o < R.kNumberOps; o += 2) {
       for (size_t i = 0; i < arraysize(kInt32Types); i++) {
@@ -1176,7 +1120,7 @@
     }
   }
   {
-    JSBitwiseShiftTypedLoweringTester R(language_mode);
+    JSBitwiseShiftTypedLoweringTester R;
 
     for (int o = 0; o < R.kNumberOps; o += 2) {
       for (size_t i = 0; i < arraysize(kInt32Types); i++) {
@@ -1199,7 +1143,7 @@
     }
   }
   {
-    JSBitwiseTypedLoweringTester R(language_mode);
+    JSBitwiseTypedLoweringTester R;
 
     for (int o = 0; o < R.kNumberOps; o += 2) {
       Node* n0 = R.Parameter(I32Type(R.signedness[o]));
@@ -1222,8 +1166,7 @@
   }
 }
 
-
-TEST_WITH_STRONG(Int32Comparisons) {
+TEST(Int32Comparisons) {
   JSTypedLoweringTester R;
 
   struct Entry {
@@ -1235,17 +1178,16 @@
   };
 
   Entry ops[] = {
-      {R.javascript.LessThan(language_mode), R.machine.Uint32LessThan(),
+      {R.javascript.LessThan(), R.machine.Uint32LessThan(),
        R.machine.Int32LessThan(), R.simplified.NumberLessThan(), false},
-      {R.javascript.LessThanOrEqual(language_mode),
-       R.machine.Uint32LessThanOrEqual(), R.machine.Int32LessThanOrEqual(),
-       R.simplified.NumberLessThanOrEqual(), false},
-      {R.javascript.GreaterThan(language_mode), R.machine.Uint32LessThan(),
+      {R.javascript.LessThanOrEqual(), R.machine.Uint32LessThanOrEqual(),
+       R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
+       false},
+      {R.javascript.GreaterThan(), R.machine.Uint32LessThan(),
        R.machine.Int32LessThan(), R.simplified.NumberLessThan(), true},
-      {R.javascript.GreaterThanOrEqual(language_mode),
-       R.machine.Uint32LessThanOrEqual(), R.machine.Int32LessThanOrEqual(),
-       R.simplified.NumberLessThanOrEqual(), true}
-  };
+      {R.javascript.GreaterThanOrEqual(), 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-jump-threading.cc b/test/cctest/compiler/test-jump-threading.cc
index 8c02012..71f774f 100644
--- a/test/cctest/compiler/test-jump-threading.cc
+++ b/test/cctest/compiler/test-jump-threading.cc
@@ -108,7 +108,7 @@
 void VerifyForwarding(TestCode& code, int count, int* expected) {
   Zone local_zone;
   ZoneVector<RpoNumber> result(&local_zone);
-  JumpThreading::ComputeForwarding(&local_zone, result, &code.sequence_);
+  JumpThreading::ComputeForwarding(&local_zone, result, &code.sequence_, true);
 
   CHECK(count == static_cast<int>(result.size()));
   for (int i = 0; i < count; i++) {
diff --git a/test/cctest/compiler/test-linkage.cc b/test/cctest/compiler/test-linkage.cc
index 939b144..6722f59 100644
--- a/test/cctest/compiler/test-linkage.cc
+++ b/test/cctest/compiler/test-linkage.cc
@@ -71,20 +71,6 @@
 }
 
 
-TEST(TestLinkageCodeStubIncoming) {
-  Isolate* isolate = CcTest::InitIsolateOnce();
-  Zone zone;
-  ToNumberStub stub(isolate);
-  CompilationInfo info(&stub, isolate, &zone);
-  CallDescriptor* descriptor = Linkage::ComputeIncoming(&zone, &info);
-  CHECK(descriptor);
-  CHECK_EQ(0, static_cast<int>(descriptor->StackParameterCount()));
-  CHECK_EQ(1, static_cast<int>(descriptor->ReturnCount()));
-  CHECK_EQ(Operator::kNoProperties, descriptor->properties());
-  CHECK_EQ(false, descriptor->IsJSFunctionCall());
-}
-
-
 TEST(TestLinkageJSCall) {
   HandleAndZoneScope handles;
   Handle<JSFunction> function = Compile("a + c");
@@ -109,6 +95,20 @@
 
 
 TEST(TestLinkageStubCall) {
+  Isolate* isolate = CcTest::InitIsolateOnce();
+  Zone zone;
+  ToNumberStub stub(isolate);
+  CompilationInfo info("test", isolate, &zone, Code::ComputeFlags(Code::STUB));
+  CallInterfaceDescriptor interface_descriptor =
+      stub.GetCallInterfaceDescriptor();
+  CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
+      isolate, &zone, interface_descriptor, stub.GetStackParameterCount(),
+      CallDescriptor::kNoFlags, Operator::kNoProperties);
+  CHECK(descriptor);
+  CHECK_EQ(0, static_cast<int>(descriptor->StackParameterCount()));
+  CHECK_EQ(1, static_cast<int>(descriptor->ReturnCount()));
+  CHECK_EQ(Operator::kNoProperties, descriptor->properties());
+  CHECK_EQ(false, descriptor->IsJSFunctionCall());
   // TODO(titzer): test linkage creation for outgoing stub calls.
 }
 
diff --git a/test/cctest/compiler/test-pipeline.cc b/test/cctest/compiler/test-pipeline.cc
index f4ffd02..35e3427 100644
--- a/test/cctest/compiler/test-pipeline.cc
+++ b/test/cctest/compiler/test-pipeline.cc
@@ -18,7 +18,7 @@
   ParseInfo parse_info(zone, function);
   CHECK(Compiler::ParseAndAnalyze(&parse_info));
   CompilationInfo info(&parse_info);
-  info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
+  info.SetOptimizing();
 
   Pipeline pipeline(&info);
   Handle<Code> code = pipeline.GenerateCode();
diff --git a/test/cctest/compiler/test-run-bytecode-graph-builder.cc b/test/cctest/compiler/test-run-bytecode-graph-builder.cc
index 88555b7..9a03822 100644
--- a/test/cctest/compiler/test-run-bytecode-graph-builder.cc
+++ b/test/cctest/compiler/test-run-bytecode-graph-builder.cc
@@ -16,6 +16,14 @@
 namespace internal {
 namespace compiler {
 
+#define SHARD_TEST_BY_2(x)    \
+  TEST(x##_0) { Test##x(0); } \
+  TEST(x##_1) { Test##x(1); }
+#define SHARD_TEST_BY_4(x)    \
+  TEST(x##_0) { Test##x(0); } \
+  TEST(x##_1) { Test##x(1); } \
+  TEST(x##_2) { Test##x(2); } \
+  TEST(x##_3) { Test##x(3); }
 
 static const char kFunctionName[] = "f";
 
@@ -70,7 +78,7 @@
     i::FLAG_ignition = true;
     i::FLAG_always_opt = false;
     i::FLAG_allow_natives_syntax = true;
-    i::FLAG_ignition_fallback_on_eval_and_catch = false;
+    i::FLAG_loop_assignment_analysis = false;
     // Set ignition filter flag via SetFlagsFromString to avoid double-free
     // (or potential leak with StrDup() based on ownership confusion).
     ScopedVector<char> ignition_filter(64);
@@ -119,13 +127,13 @@
         Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
     CHECK(function->shared()->HasBytecodeArray());
 
+    // TODO(mstarzinger): We should be able to prime CompilationInfo without
+    // having to instantiate a ParseInfo first. Fix this!
     ParseInfo parse_info(zone_, function);
 
     CompilationInfo compilation_info(&parse_info);
-    compilation_info.SetOptimizing(BailoutId::None(), Handle<Code>());
+    compilation_info.SetOptimizing();
     compilation_info.MarkAsDeoptimizationEnabled();
-    // TODO(mythria): Remove this step once parse_info is not needed.
-    CHECK(Compiler::ParseAndAnalyze(&parse_info));
     compiler::Pipeline pipeline(&compilation_info);
     Handle<Code> code = pipeline.GenerateCode();
     function->ReplaceCode(*code);
@@ -205,8 +213,7 @@
       {"return 'catfood';", {factory->NewStringFromStaticChars("catfood")}},
       {"return NaN;", {factory->nan_value()}}};
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -233,8 +240,7 @@
       {"return 25 % 7;", {factory->NewNumberFromInt(4)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -292,8 +298,7 @@
         factory->NewStringFromStaticChars("abc"),
         factory->NewStringFromStaticChars("def")}}};
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s(p1, p2) { %s }\n%s(0, 0);", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -337,8 +342,7 @@
         BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(2048);
     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -394,8 +398,7 @@
         factory->NewNumberFromInt(100)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(2048);
     SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0);", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -409,8 +412,7 @@
   }
 }
 
-
-TEST(BytecodeGraphBuilderNamedStore) {
+void TestBytecodeGraphBuilderNamedStore(size_t shard) {
   HandleAndZoneScope scope;
   Isolate* isolate = scope.main_isolate();
   Zone* zone = scope.main_zone();
@@ -445,8 +447,8 @@
         BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    if ((i % 2) != shard) continue;
     ScopedVector<char> script(3072);
     SNPrintF(script, "function %s(p1) { %s };\n%s({});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -459,8 +461,9 @@
   }
 }
 
+SHARD_TEST_BY_2(BytecodeGraphBuilderNamedStore)
 
-TEST(BytecodeGraphBuilderKeyedStore) {
+void TestBytecodeGraphBuilderKeyedStore(size_t shard) {
   HandleAndZoneScope scope;
   Isolate* isolate = scope.main_isolate();
   Zone* zone = scope.main_zone();
@@ -503,8 +506,8 @@
         factory->NewNumberFromInt(100)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    if ((i % 2) != shard) continue;
     ScopedVector<char> script(2048);
     SNPrintF(script, "function %s(p1, p2) { %s };\n%s({});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -517,6 +520,7 @@
   }
 }
 
+SHARD_TEST_BY_2(BytecodeGraphBuilderKeyedStore)
 
 TEST(BytecodeGraphBuilderPropertyCall) {
   HandleAndZoneScope scope;
@@ -538,8 +542,7 @@
             "  return a + b + c + d + e + f + g + h;}})")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(2048);
     SNPrintF(script, "function %s(p1) { %s };\n%s({func() {}});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -582,8 +585,7 @@
        {factory->NewNumberFromInt(25)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
     auto callable = tester.GetCallable<>();
     Handle<Object> return_value = callable().ToHandleChecked();
@@ -621,8 +623,7 @@
        {factory->NewNumberFromInt(25)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
     auto callable = tester.GetCallable<>();
     Handle<Object> return_value = callable().ToHandleChecked();
@@ -649,8 +650,7 @@
         BytecodeGraphTester::NewObject("[1, 2, 3]")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
     auto callable = tester.GetCallable<Handle<Object>>();
     Handle<Object> return_value =
@@ -659,8 +659,7 @@
   }
 }
 
-
-TEST(BytecodeGraphBuilderGlobals) {
+void TestBytecodeGraphBuilderGlobals(size_t shard) {
   HandleAndZoneScope scope;
   Isolate* isolate = scope.main_isolate();
   Zone* zone = scope.main_zone();
@@ -700,8 +699,8 @@
        {factory->NewStringFromStaticChars("number")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    if ((i % 2) != shard) continue;
     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
     auto callable = tester.GetCallable<>();
     Handle<Object> return_value = callable().ToHandleChecked();
@@ -709,6 +708,7 @@
   }
 }
 
+SHARD_TEST_BY_2(BytecodeGraphBuilderGlobals)
 
 TEST(BytecodeGraphBuilderToObject) {
   // TODO(mythria): tests for ToObject. Needs ForIn.
@@ -746,8 +746,7 @@
        {factory->NewNumberFromInt(10)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s() { %s }\n%s({});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -778,8 +777,7 @@
        {factory->false_value(), factory->NewStringFromStaticChars("abc")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -816,8 +814,7 @@
         factory->NewStringFromStaticChars("abc")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -871,8 +868,7 @@
        {factory->nan_value(), factory->NewStringFromStaticChars("String")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -911,8 +907,7 @@
         BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -966,8 +961,7 @@
        {factory->true_value()}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "%s %s({});", snippets[i].code_snippet, kFunctionName);
 
@@ -1003,8 +997,7 @@
       {"return delete z;", {factory->false_value()}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
              function_epilogue);
@@ -1045,8 +1038,7 @@
       {"'use strict'; obj.val = 23.456; return obj.val;",
        {factory->NewNumber(23.456)}}};
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
              function_epilogue);
@@ -1089,8 +1081,7 @@
       {"'use strict';" REPEAT_256(SPACE, "y = 2.3;") "return obj.val = 23.456;",
        {factory->NewNumber(23.456)}}};
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(3072);
     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
              function_epilogue);
@@ -1120,8 +1111,7 @@
        {handle(Smi::FromInt(30), isolate)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1173,8 +1163,7 @@
        {factory->NewStringFromStaticChars("object")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1202,8 +1191,7 @@
        {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s(p1) { %s }\n%s(0);", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1234,8 +1222,7 @@
        {factory->NewStringFromStaticChars("undefined")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
     auto callable = tester.GetCallable<>();
     Handle<Object> return_value = callable().ToHandleChecked();
@@ -1366,8 +1353,7 @@
         factory->NewNumberFromInt(1)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1399,8 +1385,7 @@
        {factory->true_value(), factory->undefined_value()}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1413,6 +1398,98 @@
   }
 }
 
+TEST(BytecodeGraphBuilderTryCatch) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+
+  ExpectedSnippet<0> snippets[] = {
+      {"var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
+       {handle(Smi::FromInt(2), isolate)}},
+      {"var a; try { undef.x } catch(e) { a = 2 }; return a;",
+       {handle(Smi::FromInt(2), isolate)}},
+      {"var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
+       {handle(Smi::FromInt(3), isolate)}},
+      {"var a; try { throw 1 } catch(e) { a = e + 2 };"
+       "       try { throw a } catch(e) { a = e + 3 }; return a;",
+       {handle(Smi::FromInt(6), isolate)}},
+  };
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+}
+
+TEST(BytecodeGraphBuilderTryFinally1) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+
+  ExpectedSnippet<0> snippets[] = {
+      {"var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
+       {handle(Smi::FromInt(4), isolate)}},
+      {"var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
+       {handle(Smi::FromInt(23), isolate)}},
+      {"var a = 1; try { a = 2; throw 23; } finally { return a; };",
+       {handle(Smi::FromInt(2), isolate)}},
+      {"var a = 1; for (var i = 10; i < 20; i += 5) {"
+       "  try { a = 2; break; } finally { a = 3; }"
+       "} return a + i;",
+       {handle(Smi::FromInt(13), isolate)}},
+      {"var a = 1; for (var i = 10; i < 20; i += 5) {"
+       "  try { a = 2; continue; } finally { a = 3; }"
+       "} return a + i;",
+       {handle(Smi::FromInt(23), isolate)}},
+      {"var a = 1; try { a = 2;"
+       "  try { a = 3; throw 23; } finally { a = 4; }"
+       "} catch(e) { a = a + e; } return a;",
+       {handle(Smi::FromInt(27), isolate)}},
+  };
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+}
+
+TEST(BytecodeGraphBuilderTryFinally2) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+
+  ExpectedSnippet<0, const char*> snippets[] = {
+      {"var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
+       {"Uncaught 23"}},
+      {"var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
+       {"Uncaught 42"}},
+  };
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+    v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
+    CHECK(
+        message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+            .FromJust());
+  }
+}
 
 TEST(BytecodeGraphBuilderThrow) {
   HandleAndZoneScope scope;
@@ -1426,15 +1503,14 @@
       {"throw 1;", {"Uncaught 1"}},
       {"throw 'Error';", {"Uncaught Error"}},
       {"throw 'Error1'; throw 'Error2'", {"Uncaught Error1"}},
-      // TODO(mythria): Enable these tests when JumpIfTrue is supported.
-      // {"var a = true; if (a) { throw 'Error'; }", {"Error"}},
+      {"var a = true; if (a) { throw 'Error'; }", {"Uncaught Error"}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
+
     BytecodeGraphTester tester(isolate, zone, script.start());
     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
     v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
@@ -1492,8 +1568,7 @@
        {factory->NewStringFromStaticChars("innermost inner_changed outer")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "%s", snippets[i].code_snippet);
 
@@ -1558,8 +1633,7 @@
        "f(0);",
        {factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}};
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "%s", snippets[i].code_snippet);
 
@@ -1585,10 +1659,13 @@
        {factory->undefined_value()}},
       {"function f(a) {'use strict'; return arguments[0];}",
        {factory->undefined_value()}},
+      {"function f(...restArgs) {return restArgs[0];}",
+       {factory->undefined_value()}},
+      {"function f(a, ...restArgs) {return restArgs[0];}",
+       {factory->undefined_value()}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
 
@@ -1631,8 +1708,7 @@
         factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(1024);
     SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
 
@@ -1647,6 +1723,48 @@
   }
 }
 
+TEST(BytecodeGraphBuilderCreateRestArguments) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+  Factory* factory = isolate->factory();
+
+  ExpectedSnippet<3> snippets[] = {
+      {"function f(...restArgs) {return restArgs[0];}",
+       {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
+        factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+      {"function f(a, b, ...restArgs) {return restArgs[0];}",
+       {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
+        factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+      {"function f(a, b, ...restArgs) {return arguments[2];}",
+       {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
+        factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+      {"function f(a, ...restArgs) { return restArgs[2];}",
+       {factory->undefined_value(), factory->NewNumberFromInt(1),
+        factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+      {"function f(a, ...restArgs) { return arguments[0] + restArgs[1];}",
+       {factory->NewNumberFromInt(4), factory->NewNumberFromInt(1),
+        factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+      {"function inline_func(a, ...restArgs) { return restArgs[0] }"
+       "function f(a, b, c) {return inline_func(b, c) + arguments[0];}",
+       {factory->NewNumberFromInt(31), factory->NewNumberFromInt(1),
+        factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
+  };
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable =
+        tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
+    Handle<Object> return_value =
+        callable(snippets[i].parameter(0), snippets[i].parameter(1),
+                 snippets[i].parameter(2))
+            .ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+}
 
 TEST(BytecodeGraphBuilderRegExpLiterals) {
   HandleAndZoneScope scope;
@@ -1671,8 +1789,7 @@
        {factory->NewStringFromStaticChars("AbC")}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(4096);
     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1712,8 +1829,7 @@
       {"var t = 't'; return [[t, t + 'est'], [1 + t]][1][0];",
        {factory->NewStringFromStaticChars("1t")}}};
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(4096);
     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1778,8 +1894,7 @@
        {factory->NewNumberFromInt(987)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(4096);
     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1856,10 +1971,38 @@
        "   if (p1 < -10) { return -2; } else { return -1; }\n"
        "}",
        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-10)}},
+      {"var b = 20, c;"
+       "if (p1 >= 0) {\n"
+       "   if (b > 0) { c = 2; } else { c = 3; }\n"
+       "} else {\n"
+       "   if (b < -10) { c = -2; } else { c = -1; }\n"
+       "}"
+       "return c;",
+       {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-1)}},
+      {"var b = 20, c = 10;"
+       "if (p1 >= 0) {\n"
+       "   if (b < 0) { c = 2; }\n"
+       "} else {\n"
+       "   if (b < -10) { c = -2; } else { c = -1; }\n"
+       "}"
+       "return c;",
+       {factory->NewNumberFromInt(10), factory->NewNumberFromInt(1)}},
+      {"var x = 2, a = 10, b = 20, c, d;"
+       "x = 0;"
+       "if (a) {\n"
+       "   b = x;"
+       "   if (b > 0) { c = 2; } else { c = 3; }\n"
+       "   x = 4; d = 2;"
+       "} else {\n"
+       "   d = 3;\n"
+       "}"
+       "x = d;"
+       "function f1() {x}"
+       "return x + c;",
+       {factory->NewNumberFromInt(5), factory->NewNumberFromInt(-1)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(2048);
     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1890,8 +2033,7 @@
        {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(20)}},
   };
 
-  size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
-  for (size_t i = 0; i < num_snippets; i++) {
+  for (size_t i = 0; i < arraysize(snippets); i++) {
     ScopedVector<char> script(2048);
     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
              snippets[i].code_snippet, kFunctionName);
@@ -1952,6 +2094,54 @@
   }
 }
 
+TEST(BytecodeGraphBuilderSwitchMerge) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+  Factory* factory = isolate->factory();
+
+  const char* switch_code =
+      "var x = 10;"
+      "switch (p1) {\n"
+      "  case 1: x = 0;\n"
+      "  case 2: x = 1;\n"
+      "  case 3:\n"
+      "  case 4: x = 2; break;\n"
+      "  case 5: x = 3;\n"
+      "  case 9: break;\n"
+      "  default: x = 4;\n"
+      "}\n"
+      "return x;";
+
+  ExpectedSnippet<1> snippets[] = {
+      {switch_code,
+       {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1)}},
+      {switch_code,
+       {factory->NewNumberFromInt(2), factory->NewNumberFromInt(2)}},
+      {switch_code,
+       {factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+      {switch_code,
+       {factory->NewNumberFromInt(2), factory->NewNumberFromInt(4)}},
+      {switch_code,
+       {factory->NewNumberFromInt(3), factory->NewNumberFromInt(5)}},
+      {switch_code,
+       {factory->NewNumberFromInt(10), factory->NewNumberFromInt(9)}},
+      {switch_code,
+       {factory->NewNumberFromInt(4), factory->NewNumberFromInt(6)}},
+  };
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(2048);
+    SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<Handle<Object>>();
+    Handle<Object> return_value =
+        callable(snippets[i].parameter(0)).ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+}
 
 TEST(BytecodeGraphBuilderNestedSwitch) {
   HandleAndZoneScope scope;
@@ -2294,12 +2484,102 @@
 }
 
 
-TEST(JumpWithConstantsAndWideConstants) {
+TEST(BytecodeGraphBuilderForOf) {
   HandleAndZoneScope scope;
-  auto isolate = scope.main_isolate();
-  const int kStep = 19;
-  int start = 7;
-  for (int constants = start; constants < 256 + 3 * kStep; constants += kStep) {
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+  Factory* factory = isolate->factory();
+  ExpectedSnippet<0> snippets[] = {
+      {"  var r = 0;\n"
+       "  for (var a of [0,6,7,9]) { r += a; }\n"
+       "  return r;\n",
+       {handle(Smi::FromInt(22), isolate)}},
+      {"  var r = '';\n"
+       "  for (var a of 'foobar') { r = a + r; }\n"
+       "  return r;\n",
+       {factory->NewStringFromStaticChars("raboof")}},
+      {"  var a = [1, 2, 3];\n"
+       "  a.name = 4;\n"
+       "  var r = 0;\n"
+       "  for (var x of a) { r += x; }\n"
+       "  return r;\n",
+       {handle(Smi::FromInt(6), isolate)}},
+      {"  var r = '';\n"
+       "  var data = [1, 2, 3]; \n"
+       "  for (a of data) { delete data[0]; r += a; } return r;",
+       {factory->NewStringFromStaticChars("123")}},
+      {"  var r = '';\n"
+       "  var data = [1, 2, 3]; \n"
+       "  for (a of data) { delete data[2]; r += a; } return r;",
+       {factory->NewStringFromStaticChars("12undefined")}},
+      {"  var r = '';\n"
+       "  var data = [1, 2, 3]; \n"
+       "  for (a of data) { delete data; r += a; } return r;",
+       {factory->NewStringFromStaticChars("123")}},
+      {"  var r = '';\n"
+       "  var input = 'foobar';\n"
+       "  for (var a of input) {\n"
+       "    if (a == 'b') break;\n"
+       "    r += a;\n"
+       "  }\n"
+       "  return r;\n",
+       {factory->NewStringFromStaticChars("foo")}},
+      {"  var r = '';\n"
+       "  var input = 'foobar';\n"
+       "  for (var a of input) {\n"
+       "    if (a == 'b') continue;\n"
+       "    r += a;\n"
+       "  }\n"
+       "  return r;\n",
+       {factory->NewStringFromStaticChars("fooar")}},
+      {"  var r = '';\n"
+       "  var data = [1, 2, 3, 4]; \n"
+       "  for (a of data) { data[2] = 567; r += a; }\n"
+       "  return r;\n",
+       {factory->NewStringFromStaticChars("125674")}},
+      {"  var r = '';\n"
+       "  var data = [1, 2, 3, 4]; \n"
+       "  for (a of data) { data[4] = 567; r += a; }\n"
+       "  return r;\n",
+       {factory->NewStringFromStaticChars("1234567")}},
+      {"  var r = '';\n"
+       "  var data = [1, 2, 3, 4]; \n"
+       "  for (a of data) { data[5] = 567; r += a; }\n"
+       "  return r;\n",
+       {factory->NewStringFromStaticChars("1234undefined567")}},
+      {"  var r = '';\n"
+       "  var obj = new Object();\n"
+       "  obj[Symbol.iterator] = function() { return {\n"
+       "    index: 3,\n"
+       "    data: ['a', 'b', 'c', 'd'],"
+       "    next: function() {"
+       "      return {"
+       "        done: this.index == -1,\n"
+       "        value: this.index < 0 ? undefined : this.data[this.index--]\n"
+       "      }\n"
+       "    }\n"
+       "    }}\n"
+       "  for (a of obj) { r += a }\n"
+       "  return r;\n",
+       {factory->NewStringFromStaticChars("dcba")}},
+  };
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+}
+
+void TestJumpWithConstantsAndWideConstants(size_t shard) {
+  const int kStep = 46;
+  int start = static_cast<int>(7 + 17 * shard);
+  for (int constants = start; constants < 300; constants += kStep) {
     std::stringstream filler_os;
     // Generate a string that consumes constant pool entries and
     // spread out branch distances in script below.
@@ -2321,11 +2601,14 @@
     script_os << "}\n";
     script_os << kFunctionName << "(0);\n";
     std::string script(script_os.str());
+
+    HandleAndZoneScope scope;
+    auto isolate = scope.main_isolate();
     auto factory = isolate->factory();
     auto zone = scope.main_zone();
+    BytecodeGraphTester tester(isolate, zone, script.c_str());
+    auto callable = tester.GetCallable<Handle<Object>>();
     for (int a = 0; a < 3; a++) {
-      BytecodeGraphTester tester(isolate, zone, script.c_str());
-      auto callable = tester.GetCallable<Handle<Object>>();
       Handle<Object> return_val =
           callable(factory->NewNumberFromInt(a)).ToHandleChecked();
       static const int results[] = {11, 12, 2};
@@ -2334,6 +2617,368 @@
   }
 }
 
+SHARD_TEST_BY_4(JumpWithConstantsAndWideConstants)
+
+TEST(BytecodeGraphBuilderDoExpressions) {
+  bool old_flag = FLAG_harmony_do_expressions;
+  FLAG_harmony_do_expressions = true;
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+  Factory* factory = isolate->factory();
+  ExpectedSnippet<0> snippets[] = {
+      {"var a = do {}; return a;", {factory->undefined_value()}},
+      {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
+      {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
+      {"var a = do { var x = 100; x++; }; return a;",
+       {handle(Smi::FromInt(100), isolate)}},
+      {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
+       "return i;",
+       {handle(Smi::FromInt(3), isolate)}},
+  };
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+
+  FLAG_harmony_do_expressions = old_flag;
+}
+
+TEST(BytecodeGraphBuilderWithStatement) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+
+  ExpectedSnippet<0> snippets[] = {
+      {"with({x:42}) return x;", {handle(Smi::FromInt(42), isolate)}},
+      {"with({}) { var y = 10; return y;}",
+       {handle(Smi::FromInt(10), isolate)}},
+      {"var y = {x:42};"
+       " function inner() {"
+       "   var x = 20;"
+       "   with(y) return x;"
+       "}"
+       "return inner();",
+       {handle(Smi::FromInt(42), isolate)}},
+      {"var y = {x:42};"
+       " function inner(o) {"
+       "   var x = 20;"
+       "   with(o) return x;"
+       "}"
+       "return inner(y);",
+       {handle(Smi::FromInt(42), isolate)}},
+  };
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+}
+
+TEST(BytecodeGraphBuilderConstDeclaration) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+  Factory* factory = isolate->factory();
+
+  ExpectedSnippet<0> snippets[] = {
+      {"const x = 3; return x;", {handle(Smi::FromInt(3), isolate)}},
+      {"let x = 10; x = x + 20; return x;",
+       {handle(Smi::FromInt(30), isolate)}},
+      {"let x = 10; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
+      {"let x; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
+      {"let x; return x;", {factory->undefined_value()}},
+      {"var x = 10; { let x = 30; } return x;",
+       {handle(Smi::FromInt(10), isolate)}},
+      {"let x = 10; { let x = 20; } return x;",
+       {handle(Smi::FromInt(10), isolate)}},
+      {"var x = 10; eval('let x = 20;'); return x;",
+       {handle(Smi::FromInt(10), isolate)}},
+      {"var x = 10; eval('const x = 20;'); return x;",
+       {handle(Smi::FromInt(10), isolate)}},
+      {"var x = 10; { const x = 20; } return x;",
+       {handle(Smi::FromInt(10), isolate)}},
+      {"var x = 10; { const x = 20; return x;} return -1;",
+       {handle(Smi::FromInt(20), isolate)}},
+      {"var a = 10;\n"
+       "for (var i = 0; i < 10; ++i) {\n"
+       " const x = i;\n"  // const declarations are block scoped.
+       " a = a + x;\n"
+       "}\n"
+       "return a;\n",
+       {handle(Smi::FromInt(55), isolate)}},
+  };
+
+  // Tests for sloppy mode.
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+
+  // Tests for strict mode.
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+}
+
+TEST(BytecodeGraphBuilderConstDeclarationLookupSlots) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+  Factory* factory = isolate->factory();
+
+  ExpectedSnippet<0> snippets[] = {
+      {"const x = 3; function f1() {return x;}; return x;",
+       {handle(Smi::FromInt(3), isolate)}},
+      {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
+       {handle(Smi::FromInt(30), isolate)}},
+      {"let x; x = 20; function f1() {return x;}; return x;",
+       {handle(Smi::FromInt(20), isolate)}},
+      {"let x; function f1() {return x;}; return x;",
+       {factory->undefined_value()}},
+  };
+
+  // Tests for sloppy mode.
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+
+  // Tests for strict mode.
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+}
+
+TEST(BytecodeGraphBuilderConstInLookupContextChain) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+
+  const char* prologue =
+      "function OuterMost() {\n"
+      "  const outerConst = 10;\n"
+      "  let outerLet = 20;\n"
+      "  function Outer() {\n"
+      "    function Inner() {\n"
+      "      this.innerFunc = function() { ";
+  const char* epilogue =
+      "      }\n"
+      "    }\n"
+      "    this.getInnerFunc ="
+      "         function() {return new Inner().innerFunc;}\n"
+      "  }\n"
+      "  this.getOuterFunc ="
+      "     function() {return new Outer().getInnerFunc();}"
+      "}\n"
+      "var f = new OuterMost().getOuterFunc();\n"
+      "f();\n";
+
+  // Tests for let / constant.
+  ExpectedSnippet<0> const_decl[] = {
+      {"return outerConst;", {handle(Smi::FromInt(10), isolate)}},
+      {"return outerLet;", {handle(Smi::FromInt(20), isolate)}},
+      {"outerLet = 30; return outerLet;", {handle(Smi::FromInt(30), isolate)}},
+      {"var outerLet = 40; return outerLet;",
+       {handle(Smi::FromInt(40), isolate)}},
+      {"var outerConst = 50; return outerConst;",
+       {handle(Smi::FromInt(50), isolate)}},
+      {"try { outerConst = 30 } catch(e) { return -1; }",
+       {handle(Smi::FromInt(-1), isolate)}}};
+
+  for (size_t i = 0; i < arraysize(const_decl); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "%s %s %s", prologue, const_decl[i].code_snippet,
+             epilogue);
+
+    BytecodeGraphTester tester(isolate, zone, script.start(), "*");
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*const_decl[i].return_value()));
+  }
+
+  // Tests for Legacy constant.
+  bool old_flag_legacy_const = FLAG_legacy_const;
+  FLAG_legacy_const = true;
+
+  ExpectedSnippet<0> legacy_const_decl[] = {
+      {"return outerConst = 23;", {handle(Smi::FromInt(23), isolate)}},
+      {"outerConst = 30; return outerConst;",
+       {handle(Smi::FromInt(10), isolate)}},
+  };
+
+  for (size_t i = 0; i < arraysize(legacy_const_decl); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "%s %s %s", prologue, legacy_const_decl[i].code_snippet,
+             epilogue);
+
+    BytecodeGraphTester tester(isolate, zone, script.start(), "*");
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*legacy_const_decl[i].return_value()));
+  }
+
+  FLAG_legacy_const = old_flag_legacy_const;
+}
+
+TEST(BytecodeGraphBuilderIllegalConstDeclaration) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+
+  ExpectedSnippet<0, const char*> illegal_const_decl[] = {
+      {"const x = x = 10 + 3; return x;",
+       {"Uncaught ReferenceError: x is not defined"}},
+      {"const x = 10; x = 20; return x;",
+       {"Uncaught TypeError: Assignment to constant variable."}},
+      {"const x = 10; { x = 20; } return x;",
+       {"Uncaught TypeError: Assignment to constant variable."}},
+      {"const x = 10; eval('x = 20;'); return x;",
+       {"Uncaught TypeError: Assignment to constant variable."}},
+      {"let x = x + 10; return x;",
+       {"Uncaught ReferenceError: x is not defined"}},
+      {"'use strict'; (function f1() { f1 = 123; })() ",
+       {"Uncaught TypeError: Assignment to constant variable."}},
+  };
+
+  // Tests for sloppy mode.
+  for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             illegal_const_decl[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+    v8::Local<v8::String> expected_string =
+        v8_str(illegal_const_decl[i].return_value());
+    CHECK(
+        message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+            .FromJust());
+  }
+
+  // Tests for strict mode.
+  for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
+             illegal_const_decl[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+    v8::Local<v8::String> expected_string =
+        v8_str(illegal_const_decl[i].return_value());
+    CHECK(
+        message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+            .FromJust());
+  }
+}
+
+TEST(BytecodeGraphBuilderLegacyConstDeclaration) {
+  bool old_flag_legacy_const = FLAG_legacy_const;
+  FLAG_legacy_const = true;
+
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+
+  ExpectedSnippet<0> snippets[] = {
+      {"const x = (x = 10) + 3; return x;",
+       {handle(Smi::FromInt(13), isolate)}},
+      {"const x = 10; x = 20; return x;", {handle(Smi::FromInt(10), isolate)}},
+      {"var a = 10;\n"
+       "for (var i = 0; i < 10; ++i) {\n"
+       " const x = i;\n"  // Legacy constants are not block scoped.
+       " a = a + x;\n"
+       "}\n"
+       "return a;\n",
+       {handle(Smi::FromInt(10), isolate)}},
+      {"const x = 20; eval('x = 10;'); return x;",
+       {handle(Smi::FromInt(20), isolate)}},
+  };
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    ScopedVector<char> script(1024);
+    SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+             snippets[i].code_snippet, kFunctionName);
+
+    BytecodeGraphTester tester(isolate, zone, script.start());
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*snippets[i].return_value()));
+  }
+
+  FLAG_legacy_const = old_flag_legacy_const;
+}
+
+TEST(BytecodeGraphBuilderDebuggerStatement) {
+  FLAG_expose_debug_as = "debug";
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+
+  ExpectedSnippet<0> snippet = {
+      "var Debug = debug.Debug;"
+      "var count = 0;"
+      "function f() {"
+      "  debugger;"
+      "}"
+      "function listener(event) {"
+      "  if (event == Debug.DebugEvent.Break) count++;"
+      "}"
+      "Debug.setListener(listener);"
+      "f();"
+      "Debug.setListener(null);"
+      "return count;",
+      {handle(Smi::FromInt(1), isolate)}};
+
+  ScopedVector<char> script(1024);
+  SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+           snippet.code_snippet, kFunctionName);
+
+  BytecodeGraphTester tester(isolate, zone, script.start());
+  auto callable = tester.GetCallable<>();
+  Handle<Object> return_value = callable().ToHandleChecked();
+  CHECK(return_value->SameValue(*snippet.return_value()));
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/compiler/test-run-deopt.cc b/test/cctest/compiler/test-run-deopt.cc
index 8b4c9dc..76dc9ac 100644
--- a/test/cctest/compiler/test-run-deopt.cc
+++ b/test/cctest/compiler/test-run-deopt.cc
@@ -84,7 +84,6 @@
 
 TEST(DeoptExceptionHandlerFinally) {
   FLAG_allow_natives_syntax = true;
-  FLAG_turbo_try_finally = true;
 
   FunctionTester T(
       "(function f() {"
@@ -98,9 +97,7 @@
 
   CompileRun("function DeoptAndThrow(f) { %DeoptimizeFunction(f); throw 0; }");
   InstallIsOptimizedHelper(CcTest::isolate());
-#if 0  // TODO(4195,mstarzinger): Reproduces on MIPS64, re-enable once fixed.
   T.CheckCall(T.false_value());
-#endif
 }
 
 
diff --git a/test/cctest/compiler/test-run-intrinsics.cc b/test/cctest/compiler/test-run-intrinsics.cc
index b201711..6e9ebf2 100644
--- a/test/cctest/compiler/test-run-intrinsics.cc
+++ b/test/cctest/compiler/test-run-intrinsics.cc
@@ -104,18 +104,6 @@
 }
 
 
-TEST(IsMinusZero) {
-  FunctionTester T("(function(a) { return %_IsMinusZero(a); })", flags);
-
-  T.CheckFalse(T.Val(1));
-  T.CheckFalse(T.Val(1.1));
-  T.CheckTrue(T.Val(-0.0));
-  T.CheckFalse(T.Val(-2));
-  T.CheckFalse(T.Val(-2.3));
-  T.CheckFalse(T.undefined());
-}
-
-
 TEST(IsRegExp) {
   FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags);
 
@@ -148,19 +136,6 @@
 }
 
 
-TEST(ObjectEquals) {
-  FunctionTester T("(function(a,b) { return %_ObjectEquals(a,b); })", flags);
-  CompileRun("var o = {}");
-
-  T.CheckTrue(T.NewObject("(o)"), T.NewObject("(o)"));
-  T.CheckTrue(T.Val("internal"), T.Val("internal"));
-  T.CheckTrue(T.true_value(), T.true_value());
-  T.CheckFalse(T.true_value(), T.false_value());
-  T.CheckFalse(T.NewObject("({})"), T.NewObject("({})"));
-  T.CheckFalse(T.Val("a"), T.Val("b"));
-}
-
-
 TEST(OneByteSeqStringGetChar) {
   FunctionTester T("(function(a,b) { return %_OneByteSeqStringGetChar(a,b); })",
                    flags);
@@ -192,15 +167,6 @@
 }
 
 
-TEST(SetValueOf) {
-  FunctionTester T("(function(a,b) { return %_SetValueOf(a,b); })", flags);
-
-  T.CheckCall(T.Val("a"), T.NewObject("(new String)"), T.Val("a"));
-  T.CheckCall(T.Val(123), T.NewObject("(new Number)"), T.Val(123));
-  T.CheckCall(T.Val("x"), T.undefined(), T.Val("x"));
-}
-
-
 TEST(StringAdd) {
   FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags);
 
diff --git a/test/cctest/compiler/test-run-jscalls.cc b/test/cctest/compiler/test-run-jscalls.cc
index 474453d..c282958 100644
--- a/test/cctest/compiler/test-run-jscalls.cc
+++ b/test/cctest/compiler/test-run-jscalls.cc
@@ -21,37 +21,36 @@
 
 TEST(SimpleCall2) {
   FunctionTester T("(function(foo,a) { return foo(a); })");
-  Handle<JSFunction> foo = T.NewFunction("(function(a) { return a; })");
-  T.Compile(foo);
+  FunctionTester U("(function(a) { return a; })");
 
-  T.CheckCall(T.Val(3), foo, T.Val(3));
-  T.CheckCall(T.Val(3.1), foo, T.Val(3.1));
-  T.CheckCall(foo, foo, foo);
-  T.CheckCall(T.Val("Abba"), foo, T.Val("Abba"));
+  T.CheckCall(T.Val(3), U.function, T.Val(3));
+  T.CheckCall(T.Val(3.1), U.function, T.Val(3.1));
+  T.CheckCall(U.function, U.function, U.function);
+  T.CheckCall(T.Val("Abba"), U.function, T.Val("Abba"));
 }
 
 
 TEST(ConstCall) {
   FunctionTester T("(function(foo,a) { return foo(a,3); })");
-  Handle<JSFunction> foo = T.NewFunction("(function(a,b) { return a + b; })");
-  T.Compile(foo);
+  FunctionTester U("(function(a,b) { return a + b; })");
 
-  T.CheckCall(T.Val(6), foo, T.Val(3));
-  T.CheckCall(T.Val(6.1), foo, T.Val(3.1));
-  T.CheckCall(T.Val("function (a,b) { return a + b; }3"), foo, foo);
-  T.CheckCall(T.Val("Abba3"), foo, T.Val("Abba"));
+  T.CheckCall(T.Val(6), U.function, T.Val(3));
+  T.CheckCall(T.Val(6.1), U.function, T.Val(3.1));
+  T.CheckCall(T.Val("function (a,b) { return a + b; }3"), U.function,
+              U.function);
+  T.CheckCall(T.Val("Abba3"), U.function, T.Val("Abba"));
 }
 
 
 TEST(ConstCall2) {
   FunctionTester T("(function(foo,a) { return foo(a,\"3\"); })");
-  Handle<JSFunction> foo = T.NewFunction("(function(a,b) { return a + b; })");
-  T.Compile(foo);
+  FunctionTester U("(function(a,b) { return a + b; })");
 
-  T.CheckCall(T.Val("33"), foo, T.Val(3));
-  T.CheckCall(T.Val("3.13"), foo, T.Val(3.1));
-  T.CheckCall(T.Val("function (a,b) { return a + b; }3"), foo, foo);
-  T.CheckCall(T.Val("Abba3"), foo, T.Val("Abba"));
+  T.CheckCall(T.Val("33"), U.function, T.Val(3));
+  T.CheckCall(T.Val("3.13"), U.function, T.Val(3.1));
+  T.CheckCall(T.Val("function (a,b) { return a + b; }3"), U.function,
+              U.function);
+  T.CheckCall(T.Val("Abba3"), U.function, T.Val("Abba"));
 }
 
 
@@ -130,7 +129,6 @@
 }
 
 
-// TODO(titzer): factor these out into test-runtime-calls.cc
 TEST(RuntimeCallCPP2) {
   FLAG_allow_natives_syntax = true;
   FunctionTester T("(function(a,b) { return %NumberImul(a, b); })");
diff --git a/test/cctest/compiler/test-run-jsexceptions.cc b/test/cctest/compiler/test-run-jsexceptions.cc
index 37b2a2d..ab8c42a 100644
--- a/test/cctest/compiler/test-run-jsexceptions.cc
+++ b/test/cctest/compiler/test-run-jsexceptions.cc
@@ -61,7 +61,6 @@
 
 
 TEST(ThrowMessageIndirectly) {
-  i::FLAG_turbo_try_finally = true;
   static const char* src =
       "(function(a, b) {"
       "  try {"
@@ -170,7 +169,6 @@
 
 
 TEST(Finally) {
-  i::FLAG_turbo_try_finally = true;
   const char* src =
       "(function(a,b) {"
       "  var r = '-';"
@@ -188,7 +186,6 @@
 
 
 TEST(FinallyBreak) {
-  i::FLAG_turbo_try_finally = true;
   const char* src =
       "(function(a,b) {"
       "  var r = '-';"
@@ -244,7 +241,6 @@
 
 
 TEST(DeoptFinallyReturn) {
-  i::FLAG_turbo_try_finally = true;
   const char* src =
       "(function f(a) {"
       "  try {"
@@ -261,7 +257,6 @@
 
 
 TEST(DeoptFinallyReThrow) {
-  i::FLAG_turbo_try_finally = true;
   const char* src =
       "(function f(a) {"
       "  try {"
@@ -272,9 +267,7 @@
       "})";
   FunctionTester T(src);
 
-#if 0  // TODO(mstarzinger): Enable once we can.
   T.CheckThrows(T.NewObject("new Error"), T.Val(1));
-#endif
 }
 
 }  // namespace compiler
diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc
index 11a3582..fba9e0e 100644
--- a/test/cctest/compiler/test-run-machops.cc
+++ b/test/cctest/compiler/test-run-machops.cc
@@ -29,6 +29,25 @@
 }
 
 
+TEST(RunWord32ReverseBits) {
+  BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
+  if (!m.machine()->Word32ReverseBits().IsSupported()) {
+    // We can only test the operator if it exists on the testing platform.
+    return;
+  }
+  m.Return(m.AddNode(m.machine()->Word32ReverseBits().op(), m.Parameter(0)));
+
+  CHECK_EQ(uint32_t(0x00000000), m.Call(uint32_t(0x00000000)));
+  CHECK_EQ(uint32_t(0x12345678), m.Call(uint32_t(0x1e6a2c48)));
+  CHECK_EQ(uint32_t(0xfedcba09), m.Call(uint32_t(0x905d3b7f)));
+  CHECK_EQ(uint32_t(0x01010101), m.Call(uint32_t(0x80808080)));
+  CHECK_EQ(uint32_t(0x01020408), m.Call(uint32_t(0x10204080)));
+  CHECK_EQ(uint32_t(0xf0703010), m.Call(uint32_t(0x080c0e0f)));
+  CHECK_EQ(uint32_t(0x1f8d0a3a), m.Call(uint32_t(0x5c50b1f8)));
+  CHECK_EQ(uint32_t(0xffffffff), m.Call(uint32_t(0xffffffff)));
+}
+
+
 TEST(RunWord32Ctz) {
   BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
   if (!m.machine()->Word32Ctz().IsSupported()) {
@@ -72,7 +91,6 @@
   CHECK_EQ(0, m.Call(uint32_t(0x9afdbc81)));
 }
 
-
 TEST(RunWord32Clz) {
   BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
   m.Return(m.Word32Clz(m.Parameter(0)));
@@ -133,6 +151,25 @@
 
 
 #if V8_TARGET_ARCH_64_BIT
+TEST(RunWord64ReverseBits) {
+  RawMachineAssemblerTester<uint64_t> m(MachineType::Uint64());
+  if (!m.machine()->Word64ReverseBits().IsSupported()) {
+    return;
+  }
+
+  m.Return(m.AddNode(m.machine()->Word64ReverseBits().op(), m.Parameter(0)));
+
+  CHECK_EQ(uint64_t(0x0000000000000000), m.Call(uint64_t(0x0000000000000000)));
+  CHECK_EQ(uint64_t(0x1234567890abcdef), m.Call(uint64_t(0xf7b3d5091e6a2c48)));
+  CHECK_EQ(uint64_t(0xfedcba0987654321), m.Call(uint64_t(0x84c2a6e1905d3b7f)));
+  CHECK_EQ(uint64_t(0x0101010101010101), m.Call(uint64_t(0x8080808080808080)));
+  CHECK_EQ(uint64_t(0x0102040803060c01), m.Call(uint64_t(0x803060c010204080)));
+  CHECK_EQ(uint64_t(0xf0703010e060200f), m.Call(uint64_t(0xf0040607080c0e0f)));
+  CHECK_EQ(uint64_t(0x2f8a6df01c21fa3b), m.Call(uint64_t(0xdc5f84380fb651f4)));
+  CHECK_EQ(uint64_t(0xffffffffffffffff), m.Call(uint64_t(0xffffffffffffffff)));
+}
+
+
 TEST(RunWord64Clz) {
   BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint64());
   m.Return(m.Word64Clz(m.Parameter(0)));
@@ -3534,7 +3571,7 @@
   const int kNumElems = 3;
   Type buffer[kNumElems];
 
-  // initialize the buffer with raw data.
+  // 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);
@@ -3543,14 +3580,14 @@
   // Test with various large and small offsets.
   for (int offset = -1; offset <= 200000; offset *= -5) {
     for (int i = 0; i < kNumElems; i++) {
-      RawMachineAssemblerTester<Type> m;
+      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));
 
-      Type expected = buffer[i];
-      Type actual = m.Call();
-      CHECK(expected == actual);
+      volatile Type expected = buffer[i];
+      volatile Type actual = m.Call();
+      CHECK_EQ(expected, actual);
     }
   }
 }
@@ -3564,9 +3601,11 @@
   RunLoadImmIndex<int32_t>(MachineType::Int32());
   RunLoadImmIndex<uint32_t>(MachineType::Uint32());
   RunLoadImmIndex<int32_t*>(MachineType::AnyTagged());
-
-  // TODO(titzer): test kRepBit loads
-  // TODO(titzer): test MachineType::Float64() loads
+  RunLoadImmIndex<float>(MachineType::Float32());
+  RunLoadImmIndex<double>(MachineType::Float64());
+  if (kPointerSize == 8) {
+    RunLoadImmIndex<int64_t>(MachineType::Int64());
+  }
   // TODO(titzer): test various indexing modes.
 }
 
@@ -4124,6 +4163,43 @@
 }
 
 
+TEST(RunTruncateFloat32ToInt32) {
+  BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Float32());
+  m.Return(m.TruncateFloat32ToInt32(m.Parameter(0)));
+  FOR_FLOAT32_INPUTS(i) {
+    if (*i <= static_cast<float>(std::numeric_limits<int32_t>::max()) &&
+        *i >= static_cast<float>(std::numeric_limits<int32_t>::min())) {
+      CheckFloatEq(static_cast<int32_t>(*i), m.Call(*i));
+    }
+  }
+}
+
+
+TEST(RunTruncateFloat32ToUint32) {
+  BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Float32());
+  m.Return(m.TruncateFloat32ToUint32(m.Parameter(0)));
+  {
+    FOR_UINT32_INPUTS(i) {
+      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.
+      if (input < static_cast<float>(std::numeric_limits<uint32_t>::max())) {
+        CHECK_EQ(static_cast<uint32_t>(input), m.Call(input));
+      }
+    }
+  }
+  {
+    FOR_FLOAT32_INPUTS(i) {
+      if (*i <= static_cast<float>(std::numeric_limits<uint32_t>::max()) &&
+          *i >= static_cast<float>(std::numeric_limits<uint32_t>::min())) {
+        CheckFloatEq(static_cast<uint32_t>(*i), m.Call(*i));
+      }
+    }
+  }
+}
+
+
 TEST(RunChangeFloat64ToInt32_A) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   double magic = 11.1;
@@ -5577,6 +5653,79 @@
 }
 #endif  // USE_SIMULATOR
 
+template <typename T>
+void TestExternalReferenceFunction(
+    BufferedRawMachineAssemblerTester<int32_t>* m, ExternalReference ref,
+    T (*comparison)(T)) {
+  T parameter;
+
+  Node* function = m->ExternalConstant(ref);
+  m->CallCFunction1(MachineType::Pointer(), MachineType::Pointer(), function,
+                    m->PointerConstant(&parameter));
+  m->Return(m->Int32Constant(4356));
+  FOR_FLOAT64_INPUTS(i) {
+    parameter = *i;
+    m->Call();
+    CheckDoubleEq(comparison(*i), parameter);
+  }
+}
+
+TEST(RunCallExternalReferenceF32Trunc) {
+  BufferedRawMachineAssemblerTester<int32_t> m;
+  ExternalReference ref =
+      ExternalReference::f32_trunc_wrapper_function(m.isolate());
+  TestExternalReferenceFunction<float>(&m, ref, truncf);
+}
+
+TEST(RunCallExternalReferenceF32Floor) {
+  BufferedRawMachineAssemblerTester<int32_t> m;
+  ExternalReference ref =
+      ExternalReference::f32_floor_wrapper_function(m.isolate());
+  TestExternalReferenceFunction<float>(&m, ref, floorf);
+}
+
+TEST(RunCallExternalReferenceF32Ceil) {
+  BufferedRawMachineAssemblerTester<int32_t> m;
+  ExternalReference ref =
+      ExternalReference::f32_ceil_wrapper_function(m.isolate());
+  TestExternalReferenceFunction<float>(&m, ref, ceilf);
+}
+
+TEST(RunCallExternalReferenceF32RoundTiesEven) {
+  BufferedRawMachineAssemblerTester<int32_t> m;
+  ExternalReference ref =
+      ExternalReference::f32_nearest_int_wrapper_function(m.isolate());
+  TestExternalReferenceFunction<float>(&m, ref, nearbyintf);
+}
+
+TEST(RunCallExternalReferenceF64Trunc) {
+  BufferedRawMachineAssemblerTester<int32_t> m;
+  ExternalReference ref =
+      ExternalReference::f64_trunc_wrapper_function(m.isolate());
+  TestExternalReferenceFunction<double>(&m, ref, trunc);
+}
+
+TEST(RunCallExternalReferenceF64Floor) {
+  BufferedRawMachineAssemblerTester<int32_t> m;
+  ExternalReference ref =
+      ExternalReference::f64_floor_wrapper_function(m.isolate());
+  TestExternalReferenceFunction<double>(&m, ref, floor);
+}
+
+TEST(RunCallExternalReferenceF64Ceil) {
+  BufferedRawMachineAssemblerTester<int32_t> m;
+  ExternalReference ref =
+      ExternalReference::f64_ceil_wrapper_function(m.isolate());
+  TestExternalReferenceFunction<double>(&m, ref, ceil);
+}
+
+TEST(RunCallExternalReferenceF64RoundTiesEven) {
+  BufferedRawMachineAssemblerTester<int32_t> m;
+  ExternalReference ref =
+      ExternalReference::f64_nearest_int_wrapper_function(m.isolate());
+  TestExternalReferenceFunction<double>(&m, ref, nearbyint);
+}
+
 #if V8_TARGET_ARCH_64_BIT
 // TODO(titzer): run int64 tests on all platforms when supported.
 TEST(RunCheckedLoadInt64) {
@@ -6001,6 +6150,26 @@
 }
 
 
+TEST(RunRoundInt32ToFloat32) {
+  BufferedRawMachineAssemblerTester<float> m(MachineType::Int32());
+  m.Return(m.RoundInt32ToFloat32(m.Parameter(0)));
+  FOR_INT32_INPUTS(i) {
+    volatile float expected = static_cast<float>(*i);
+    CHECK_EQ(expected, m.Call(*i));
+  }
+}
+
+
+TEST(RunRoundUint32ToFloat32) {
+  BufferedRawMachineAssemblerTester<float> m(MachineType::Uint32());
+  m.Return(m.RoundUint32ToFloat32(m.Parameter(0)));
+  FOR_UINT32_INPUTS(i) {
+    volatile float expected = static_cast<float>(*i);
+    CHECK_EQ(expected, m.Call(*i));
+  }
+}
+
+
 TEST(RunBitcastInt32ToFloat32) {
   int32_t input = 1;
   float output = 0.0;
@@ -6068,6 +6237,27 @@
   CHECK_EQ(44, r.Call(0));
 }
 
+TEST(ParentFramePointer) {
+  RawMachineAssemblerTester<int32_t> r(MachineType::Int32());
+  RawMachineLabel tlabel;
+  RawMachineLabel flabel;
+  RawMachineLabel merge;
+  Node* frame = r.LoadFramePointer();
+  Node* parent_frame = r.LoadParentFramePointer();
+  frame = r.Load(MachineType::IntPtr(), frame);
+  r.Branch(r.WordEqual(frame, parent_frame), &tlabel, &flabel);
+  r.Bind(&tlabel);
+  Node* fa = r.Int32Constant(1);
+  r.Goto(&merge);
+  r.Bind(&flabel);
+  Node* fb = r.Int32Constant(0);
+  r.Goto(&merge);
+  r.Bind(&merge);
+  Node* phi = r.Phi(MachineRepresentation::kWord32, fa, fb);
+  r.Return(phi);
+  CHECK_EQ(1, r.Call(1));
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/compiler/test-run-native-calls.cc b/test/cctest/compiler/test-run-native-calls.cc
index 791b0d7..8911409 100644
--- a/test/cctest/compiler/test-run-native-calls.cc
+++ b/test/cctest/compiler/test-run-native-calls.cc
@@ -1157,6 +1157,99 @@
 TEST(MixedParams_2) { MixedParamTest(2); }
 TEST(MixedParams_3) { MixedParamTest(3); }
 
+template <typename T>
+void TestStackSlot(MachineType slot_type, T expected) {
+  // 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;
+
+  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)};
+  Allocator palloc(parray_gp, 2, parray_fp, 2);
+  Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
+  RegisterConfig config(palloc, ralloc);
+
+  Zone zone;
+  HandleScope scope(isolate);
+  MachineSignature::Builder builder(&zone, 1, 12);
+  builder.AddReturn(MachineType::Int32());
+  for (int i = 0; i < 10; i++) {
+    builder.AddParam(MachineType::Int32());
+  }
+  builder.AddParam(slot_type);
+  builder.AddParam(MachineType::Pointer());
+  MachineSignature* sig = builder.Build();
+  CallDescriptor* desc = config.Create(&zone, sig);
+
+  // Create inner function g. g has lots of parameters so that they are passed
+  // over the stack.
+  Handle<Code> inner;
+  Graph graph(&zone);
+  RawMachineAssembler g(isolate, &graph, desc);
+
+  g.Store(slot_type.representation(), g.Parameter(11), g.Parameter(10),
+          WriteBarrierKind::kNoWriteBarrier);
+  g.Return(g.Parameter(9));
+  inner = CompileGraph("Compute", desc, &graph, g.Export());
+
+  // Create function f with a stack slot which calls the inner function g.
+  BufferedRawMachineAssemblerTester<T> f(slot_type);
+  Node* target = f.HeapConstant(inner);
+  Node* stack_slot = f.StackSlot(slot_type.representation());
+  Node* args[12];
+  for (int i = 0; i < 10; i++) {
+    args[i] = f.Int32Constant(i);
+  }
+  args[10] = f.Parameter(0);
+  args[11] = stack_slot;
+
+  f.CallN(desc, target, args);
+  f.Return(f.Load(slot_type, stack_slot, f.IntPtrConstant(0)));
+
+  CHECK_EQ(expected, f.Call(expected));
+}
+
+TEST(RunStackSlotInt32) {
+  int32_t magic = 0x12345678;
+  TestStackSlot(MachineType::Int32(), magic);
+}
+
+#if !V8_TARGET_ARCH_32_BIT
+TEST(RunStackSlotInt64) {
+  int64_t magic = 0x123456789abcdef0;
+  TestStackSlot(MachineType::Int64(), magic);
+}
+#endif
+
+TEST(RunStackSlotFloat32) {
+  float magic = 1234.125f;
+  TestStackSlot(MachineType::Float32(), magic);
+}
+
+TEST(RunStackSlotFloat64) {
+  double magic = 3456.375;
+  TestStackSlot(MachineType::Float64(), magic);
+}
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/compiler/test-run-properties.cc b/test/cctest/compiler/test-run-properties.cc
deleted file mode 100644
index 3c42102..0000000
--- a/test/cctest/compiler/test-run-properties.cc
+++ /dev/null
@@ -1,142 +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 "test/cctest/compiler/function-tester.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-template <typename U>
-static void TypedArrayLoadHelper(const char* array_type) {
-  static const uint32_t kValues[] = {
-      0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321,
-      0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff,
-      0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000};
-  EmbeddedVector<char, 1024> values_buffer;
-  StringBuilder values_builder(values_buffer.start(), values_buffer.length());
-  for (size_t i = 0; i < arraysize(kValues); ++i) {
-    values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
-  }
-
-  // Note that below source creates two different typed arrays with the same
-  // elements kind to get coverage for both (on heap / with external backing
-  // store) access patterns.
-  const char* source =
-      "(function(a) {"
-      "  var x = (a = new %sArray(%d)); %s;"
-      "  var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
-      "  if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
-      "  if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
-      "  function f(a,b) {"
-      "    a = a | 0; b = b | 0;"
-      "    return x[a] + y[b];"
-      "  }"
-      "  return f;"
-      "})()";
-  EmbeddedVector<char, 1024> source_buffer;
-  SNPrintF(source_buffer, source, array_type, arraysize(kValues),
-           values_buffer.start(), array_type, arraysize(kValues),
-           values_buffer.start(), array_type, array_type);
-
-  FunctionTester T(source_buffer.start(),
-                   CompilationInfo::kFunctionContextSpecializing |
-                       CompilationInfo::kTypingEnabled);
-  for (size_t i = 0; i < arraysize(kValues); ++i) {
-    for (size_t j = 0; j < arraysize(kValues); ++j) {
-      volatile U value_a = static_cast<U>(kValues[i]);
-      volatile U value_b = static_cast<U>(kValues[j]);
-      double expected =
-          static_cast<double>(value_a) + static_cast<double>(value_b);
-      T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
-                  T.Val(static_cast<double>(j)));
-    }
-  }
-}
-
-
-TEST(TypedArrayLoad) {
-  FLAG_typed_array_max_size_in_heap = 256;
-  TypedArrayLoadHelper<int8_t>("Int8");
-  TypedArrayLoadHelper<uint8_t>("Uint8");
-  TypedArrayLoadHelper<int16_t>("Int16");
-  TypedArrayLoadHelper<uint16_t>("Uint16");
-  TypedArrayLoadHelper<int32_t>("Int32");
-  TypedArrayLoadHelper<uint32_t>("Uint32");
-  TypedArrayLoadHelper<float>("Float32");
-  TypedArrayLoadHelper<double>("Float64");
-  // TODO(mstarzinger): Add tests for ClampedUint8.
-}
-
-
-template <typename U>
-static void TypedArrayStoreHelper(const char* array_type) {
-  static const uint32_t kValues[] = {
-      0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321,
-      0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff,
-      0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000};
-  EmbeddedVector<char, 1024> values_buffer;
-  StringBuilder values_builder(values_buffer.start(), values_buffer.length());
-  for (size_t i = 0; i < arraysize(kValues); ++i) {
-    values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
-  }
-
-  // Note that below source creates two different typed arrays with the same
-  // elements kind to get coverage for both (on heap/with external backing
-  // store) access patterns.
-  const char* source =
-      "(function(a) {"
-      "  var x = (a = new %sArray(%d)); %s;"
-      "  var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
-      "  if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
-      "  if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
-      "  function f(a,b) {"
-      "    a = a | 0; b = b | 0;"
-      "    var t = x[a];"
-      "    x[a] = y[b];"
-      "    y[b] = t;"
-      "    t = y[b];"
-      "    y[b] = x[a];"
-      "    x[a] = t;"
-      "    return x[a] + y[b];"
-      "  }"
-      "  return f;"
-      "})()";
-  EmbeddedVector<char, 2048> source_buffer;
-  SNPrintF(source_buffer, source, array_type, arraysize(kValues),
-           values_buffer.start(), array_type, arraysize(kValues),
-           values_buffer.start(), array_type, array_type);
-
-  FunctionTester T(source_buffer.start(),
-                   CompilationInfo::kFunctionContextSpecializing |
-                       CompilationInfo::kTypingEnabled);
-  for (size_t i = 0; i < arraysize(kValues); ++i) {
-    for (size_t j = 0; j < arraysize(kValues); ++j) {
-      volatile U value_a = static_cast<U>(kValues[i]);
-      volatile U value_b = static_cast<U>(kValues[j]);
-      double expected =
-          static_cast<double>(value_a) + static_cast<double>(value_b);
-      T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
-                  T.Val(static_cast<double>(j)));
-    }
-  }
-}
-
-
-TEST(TypedArrayStore) {
-  FLAG_typed_array_max_size_in_heap = 256;
-  TypedArrayStoreHelper<int8_t>("Int8");
-  TypedArrayStoreHelper<uint8_t>("Uint8");
-  TypedArrayStoreHelper<int16_t>("Int16");
-  TypedArrayStoreHelper<uint16_t>("Uint16");
-  TypedArrayStoreHelper<int32_t>("Int32");
-  TypedArrayStoreHelper<uint32_t>("Uint32");
-  TypedArrayStoreHelper<float>("Float32");
-  TypedArrayStoreHelper<double>("Float64");
-  // TODO(mstarzinger): Add tests for ClampedUint8.
-}
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/test/cctest/compiler/test-run-stubs.cc b/test/cctest/compiler/test-run-stubs.cc
index 7a2a094..c745219 100644
--- a/test/cctest/compiler/test-run-stubs.cc
+++ b/test/cctest/compiler/test-run-stubs.cc
@@ -27,8 +27,13 @@
   // Create code and an accompanying descriptor.
   StringLengthStub stub(isolate);
   Handle<Code> code = stub.GenerateCode();
-  CompilationInfo info(&stub, isolate, zone);
-  CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info);
+  CompilationInfo info("test", isolate, zone,
+                       Code::ComputeFlags(Code::HANDLER));
+  CallInterfaceDescriptor interface_descriptor =
+      stub.GetCallInterfaceDescriptor();
+  CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
+      isolate, zone, interface_descriptor, stub.GetStackParameterCount(),
+      CallDescriptor::kNoFlags, Operator::kNoProperties);
 
   // Create a function to call the code using the descriptor.
   Graph graph(zone);
diff --git a/test/cctest/compiler/value-helper.h b/test/cctest/compiler/value-helper.h
index cbde9a7..83cd33c 100644
--- a/test/cctest/compiler/value-helper.h
+++ b/test/cctest/compiler/value-helper.h
@@ -312,6 +312,23 @@
 
 #define FOR_UINT32_SHIFTS(var) for (uint32_t var = 0; var < 32; var++)
 
+// TODO(bmeurer): Drop this crap once we switch to GTest/Gmock.
+static inline void CheckFloatEq(volatile float x, volatile float y) {
+  if (std::isnan(x)) {
+    CHECK(std::isnan(y));
+  } else {
+    CHECK_EQ(x, y);
+  }
+}
+
+static inline void CheckDoubleEq(volatile double x, volatile double y) {
+  if (std::isnan(x)) {
+    CHECK(std::isnan(y));
+  } else {
+    CHECK_EQ(x, y);
+  }
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/heap/heap-tester.h b/test/cctest/heap/heap-tester.h
index 0a0860b..5d098f5 100644
--- a/test/cctest/heap/heap-tester.h
+++ b/test/cctest/heap/heap-tester.h
@@ -28,9 +28,9 @@
   V(StressHandles)                                        \
   V(TestMemoryReducerSampleJsCalls)                       \
   V(TestSizeOfObjects)                                    \
+  V(Regress587004)                                        \
   V(WriteBarriersInCopyJSObject)
 
-
 #define HEAP_TEST(Name)                                                       \
   CcTest register_test_##Name(v8::internal::HeapTester::Test##Name, __FILE__, \
                               #Name, NULL, true, true);                       \
@@ -59,25 +59,6 @@
 
   /* test-api.cc */
   static void ResetWeakHandle(bool global_gc);
-
-  /* test-spaces.cc */
-  static CompactionSpaceCollection** InitializeCompactionSpaces(Heap* heap,
-                                                                int num_spaces);
-  static void DestroyCompactionSpaces(CompactionSpaceCollection** spaces,
-                                      int num_spaces);
-  static void MergeCompactionSpaces(PagedSpace* space,
-                                    CompactionSpaceCollection** spaces,
-                                    int num_spaces);
-  static void AllocateInCompactionSpaces(CompactionSpaceCollection** spaces,
-                                         AllocationSpace id, int num_spaces,
-                                         int num_objects, int object_size);
-  static void CompactionStats(CompactionSpaceCollection** spaces,
-                              AllocationSpace id, int num_spaces,
-                              intptr_t* capacity, intptr_t* size);
-  static void TestCompactionSpaceDivide(int num_additional_objects,
-                                        int object_size,
-                                        int num_compaction_spaces,
-                                        int additional_capacity_in_bytes);
 };
 
 }  // namespace internal
diff --git a/test/cctest/heap/test-heap.cc b/test/cctest/heap/test-heap.cc
index 726887a..88aee8a 100644
--- a/test/cctest/heap/test-heap.cc
+++ b/test/cctest/heap/test-heap.cc
@@ -33,6 +33,7 @@
 #include "src/deoptimizer.h"
 #include "src/execution.h"
 #include "src/factory.h"
+#include "src/field-type.h"
 #include "src/global-handles.h"
 #include "src/heap/gc-tracer.h"
 #include "src/heap/memory-reducer.h"
@@ -1515,6 +1516,50 @@
   CHECK(function->is_compiled() || !function->IsOptimized());
 }
 
+TEST(TestUseOfIncrementalBarrierOnCompileLazy) {
+  // Turn off always_opt because it interferes with running the built-in for
+  // the last call to g().
+  i::FLAG_always_opt = false;
+  i::FLAG_allow_natives_syntax = true;
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  Factory* factory = isolate->factory();
+  Heap* heap = isolate->heap();
+  v8::HandleScope scope(CcTest::isolate());
+
+  CompileRun(
+      "function make_closure(x) {"
+      "  return function() { return x + 3 };"
+      "}"
+      "var f = make_closure(5); f();"
+      "var g = make_closure(5);");
+
+  // Check f is compiled.
+  Handle<String> f_name = factory->InternalizeUtf8String("f");
+  Handle<Object> f_value =
+      Object::GetProperty(isolate->global_object(), f_name).ToHandleChecked();
+  Handle<JSFunction> f_function = Handle<JSFunction>::cast(f_value);
+  CHECK(f_function->is_compiled());
+
+  // Check g is not compiled.
+  Handle<String> g_name = factory->InternalizeUtf8String("g");
+  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());
+
+  SimulateIncrementalMarking(heap);
+  CompileRun("%OptimizeFunctionOnNextCall(f); f();");
+
+  // g should now have available an optimized function, unmarked by gc. The
+  // CompileLazy built-in will discover it and install it in the closure, and
+  // the incremental write barrier should be used.
+  CompileRun("g();");
+  CHECK(g_function->is_compiled());
+}
 
 TEST(CompilationCacheCachingBehavior) {
   // If we do not flush code, or have the compilation cache turned off, this
@@ -3514,6 +3559,13 @@
   // The optimizer can allocate stuff, messing up the test.
   i::FLAG_crankshaft = false;
   i::FLAG_always_opt = false;
+  // Parallel compaction increases fragmentation, depending on how existing
+  // memory is distributed. Since this is non-deterministic because of
+  // concurrent sweeping, we disable it for this test.
+  i::FLAG_parallel_compaction = false;
+  // Concurrent sweeping adds non determinism, depending on when memory is
+  // available for further reuse.
+  i::FLAG_concurrent_sweeping = false;
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
   Factory* factory = isolate->factory();
@@ -4163,9 +4215,6 @@
   CHECK(shared1->code()->gc_metadata() != NULL);
 
   // Optimize function and make sure the unoptimized code is replaced.
-#ifdef DEBUG
-  FLAG_stop_at = "f";
-#endif
   CompileRun("%OptimizeFunctionOnNextCall(g);"
              "g(false);");
 
@@ -5555,8 +5604,8 @@
 
   Handle<FixedArray> o1 = isolate->factory()->NewFixedArray(kFixedArrayLen);
   Handle<FixedArray> o2 = isolate->factory()->NewFixedArray(kFixedArrayLen);
-  CHECK(heap->InNewSpace(o1->address()));
-  CHECK(heap->InNewSpace(o2->address()));
+  CHECK(heap->InNewSpace(*o1));
+  CHECK(heap->InNewSpace(*o2));
 
   HeapIterator it(heap, i::HeapIterator::kFilterUnreachable);
 
@@ -5571,33 +5620,6 @@
 }
 
 
-TEST(ArrayShiftSweeping) {
-  i::FLAG_expose_gc = true;
-  CcTest::InitializeVM();
-  v8::HandleScope scope(CcTest::isolate());
-  Isolate* isolate = CcTest::i_isolate();
-  Heap* heap = isolate->heap();
-
-  v8::Local<v8::Value> result = CompileRun(
-      "var array = new Array(400);"
-      "var tmp = new Array(1000);"
-      "array[0] = 10;"
-      "gc();"
-      "gc();"
-      "array.shift();"
-      "array;");
-
-  Handle<JSObject> o = Handle<JSObject>::cast(
-      v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(result)));
-  CHECK(heap->InOldSpace(o->elements()));
-  CHECK(heap->InOldSpace(*o));
-  Page* page = Page::FromAddress(o->elements()->address());
-  CHECK(page->parallel_sweeping_state().Value() <=
-            MemoryChunk::kSweepingFinalize ||
-        Marking::IsBlack(Marking::MarkBitFrom(o->elements())));
-}
-
-
 UNINITIALIZED_TEST(PromotionQueue) {
   i::FLAG_expose_gc = true;
   i::FLAG_max_semi_space_size = 2 * (Page::kPageSize / MB);
@@ -5681,10 +5703,12 @@
   Heap* heap = isolate->heap();
 
   Handle<Map> map1 = Map::Create(isolate, 1);
+  Handle<String> name = factory->NewStringFromStaticChars("foo");
+  name = factory->InternalizeString(name);
   Handle<Map> map2 =
-      Map::CopyWithField(map1, factory->NewStringFromStaticChars("foo"),
-                         HeapType::Any(isolate), NONE, Representation::Tagged(),
-                         OMIT_TRANSITION).ToHandleChecked();
+      Map::CopyWithField(map1, name, FieldType::Any(isolate), NONE,
+                         Representation::Tagged(), OMIT_TRANSITION)
+          .ToHandleChecked();
 
   int desired_offset = Page::kPageSize - map1->instance_size();
 
@@ -6232,7 +6256,6 @@
   const char* flag = "--turbo-filter=*";
   FlagList::SetFlagsFromString(flag, StrLength(flag));
   FLAG_always_opt = true;
-  FLAG_turbo_try_finally = true;
 
   CompileRun(test);
 }
@@ -6470,6 +6493,43 @@
   CheckDoubleEquals(2, calls_per_ms);
 }
 
+HEAP_TEST(Regress587004) {
+  FLAG_concurrent_sweeping = false;
+#ifdef VERIFY_HEAP
+  FLAG_verify_heap = false;
+#endif
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Heap* heap = CcTest::heap();
+  Isolate* isolate = CcTest::i_isolate();
+  Factory* factory = isolate->factory();
+  const int N = (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) /
+                kPointerSize;
+  Handle<FixedArray> array = factory->NewFixedArray(N, TENURED);
+  CHECK(heap->old_space()->Contains(*array));
+  Handle<Object> number = factory->NewHeapNumber(1.0);
+  CHECK(heap->InNewSpace(*number));
+  for (int i = 0; i < N; i++) {
+    array->set(i, *number);
+  }
+  heap->CollectGarbage(OLD_SPACE);
+  SimulateFullSpace(heap->old_space());
+  heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, N - 1);
+  heap->mark_compact_collector()->EnsureSweepingCompleted();
+  ByteArray* byte_array;
+  const int M = 256;
+  // Don't allow old space expansion. The test works without this flag too,
+  // but becomes very slow.
+  heap->set_force_oom(true);
+  while (heap->AllocateByteArray(M, TENURED).To(&byte_array)) {
+    for (int j = 0; j < M; j++) {
+      byte_array->set(j, 0x31);
+    }
+  }
+  // Re-enable old space expansion to avoid OOM crash.
+  heap->set_force_oom(false);
+  heap->CollectGarbage(NEW_SPACE);
+}
 
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/heap/test-spaces.cc b/test/cctest/heap/test-spaces.cc
index 2fe099d..41345bc 100644
--- a/test/cctest/heap/test-spaces.cc
+++ b/test/cctest/heap/test-spaces.cc
@@ -448,236 +448,6 @@
 }
 
 
-TEST(CompactionSpaceUsingExternalMemory) {
-  const int kObjectSize = 512;
-
-  Isolate* isolate = CcTest::i_isolate();
-  Heap* heap = isolate->heap();
-  MemoryAllocator* allocator = new MemoryAllocator(isolate);
-  CHECK(allocator != nullptr);
-  CHECK(allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize()));
-  TestMemoryAllocatorScope test_scope(isolate, allocator);
-
-  CompactionSpaceCollection* collection = new CompactionSpaceCollection(heap);
-  CompactionSpace* compaction_space = collection->Get(OLD_SPACE);
-  CHECK(compaction_space != NULL);
-  CHECK(compaction_space->SetUp());
-
-  OldSpace* old_space = new OldSpace(heap, OLD_SPACE, NOT_EXECUTABLE);
-  CHECK(old_space != NULL);
-  CHECK(old_space->SetUp());
-
-  // The linear allocation area already counts as used bytes, making
-  // exact testing impossible.
-  heap->DisableInlineAllocation();
-
-  // Test:
-  // * Allocate a backing store in old_space.
-  // * Compute the number num_rest_objects of kObjectSize objects that fit into
-  //   of available memory.
-  //   kNumRestObjects.
-  // * Add the rest of available memory to the compaction space.
-  // * Allocate kNumRestObjects in the compaction space.
-  // * Allocate one object more.
-  // * Merge the compaction space and compare the expected number of pages.
-
-  // Allocate a single object in old_space to initialize a backing page.
-  old_space->AllocateRawUnaligned(kObjectSize).ToObjectChecked();
-  // Compute the number of objects that fit into the rest in old_space.
-  intptr_t rest = static_cast<int>(old_space->Available());
-  CHECK_GT(rest, 0);
-  intptr_t num_rest_objects = rest / kObjectSize;
-  // After allocating num_rest_objects in compaction_space we allocate a bit
-  // more.
-  const intptr_t kAdditionalCompactionMemory = kObjectSize;
-  // We expect a single old_space page.
-  const intptr_t kExpectedInitialOldSpacePages = 1;
-  // We expect a single additional page in compaction space because we mostly
-  // use external memory.
-  const intptr_t kExpectedCompactionPages = 1;
-  // We expect two pages to be reachable from old_space in the end.
-  const intptr_t kExpectedOldSpacePagesAfterMerge = 2;
-
-  CHECK_EQ(old_space->CountTotalPages(), kExpectedInitialOldSpacePages);
-  CHECK_EQ(compaction_space->CountTotalPages(), 0);
-  CHECK_EQ(compaction_space->Capacity(), 0);
-  // Make the rest of memory available for compaction.
-  old_space->DivideUponCompactionSpaces(&collection, 1, rest);
-  CHECK_EQ(compaction_space->CountTotalPages(), 0);
-  CHECK_EQ(compaction_space->Capacity(), rest);
-  while (num_rest_objects-- > 0) {
-    compaction_space->AllocateRawUnaligned(kObjectSize).ToObjectChecked();
-  }
-  // We only used external memory so far.
-  CHECK_EQ(compaction_space->CountTotalPages(), 0);
-  // Additional allocation.
-  compaction_space->AllocateRawUnaligned(kAdditionalCompactionMemory)
-      .ToObjectChecked();
-  // Now the compaction space shouldve also acquired a page.
-  CHECK_EQ(compaction_space->CountTotalPages(), kExpectedCompactionPages);
-
-  old_space->MergeCompactionSpace(compaction_space);
-  CHECK_EQ(old_space->CountTotalPages(), kExpectedOldSpacePagesAfterMerge);
-
-  delete collection;
-  delete old_space;
-
-  allocator->TearDown();
-  delete allocator;
-}
-
-
-CompactionSpaceCollection** HeapTester::InitializeCompactionSpaces(
-    Heap* heap, int num_spaces) {
-  CompactionSpaceCollection** spaces =
-      new CompactionSpaceCollection*[num_spaces];
-  for (int i = 0; i < num_spaces; i++) {
-    spaces[i] = new CompactionSpaceCollection(heap);
-  }
-  return spaces;
-}
-
-
-void HeapTester::DestroyCompactionSpaces(CompactionSpaceCollection** spaces,
-                                         int num_spaces) {
-  for (int i = 0; i < num_spaces; i++) {
-    delete spaces[i];
-  }
-  delete[] spaces;
-}
-
-
-void HeapTester::MergeCompactionSpaces(PagedSpace* space,
-                                       CompactionSpaceCollection** spaces,
-                                       int num_spaces) {
-  AllocationSpace id = space->identity();
-  for (int i = 0; i < num_spaces; i++) {
-    space->MergeCompactionSpace(spaces[i]->Get(id));
-    CHECK_EQ(spaces[i]->Get(id)->accounting_stats_.Size(), 0);
-    CHECK_EQ(spaces[i]->Get(id)->accounting_stats_.Capacity(), 0);
-    CHECK_EQ(spaces[i]->Get(id)->Waste(), 0);
-  }
-}
-
-
-void HeapTester::AllocateInCompactionSpaces(CompactionSpaceCollection** spaces,
-                                            AllocationSpace id, int num_spaces,
-                                            int num_objects, int object_size) {
-  for (int i = 0; i < num_spaces; i++) {
-    for (int j = 0; j < num_objects; j++) {
-      spaces[i]->Get(id)->AllocateRawUnaligned(object_size).ToObjectChecked();
-    }
-    spaces[i]->Get(id)->EmptyAllocationInfo();
-    CHECK_EQ(spaces[i]->Get(id)->accounting_stats_.Size(),
-             num_objects * object_size);
-    CHECK_GE(spaces[i]->Get(id)->accounting_stats_.Capacity(),
-             spaces[i]->Get(id)->accounting_stats_.Size());
-  }
-}
-
-
-void HeapTester::CompactionStats(CompactionSpaceCollection** spaces,
-                                 AllocationSpace id, int num_spaces,
-                                 intptr_t* capacity, intptr_t* size) {
-  *capacity = 0;
-  *size = 0;
-  for (int i = 0; i < num_spaces; i++) {
-    *capacity += spaces[i]->Get(id)->accounting_stats_.Capacity();
-    *size += spaces[i]->Get(id)->accounting_stats_.Size();
-  }
-}
-
-
-void HeapTester::TestCompactionSpaceDivide(int num_additional_objects,
-                                           int object_size,
-                                           int num_compaction_spaces,
-                                           int additional_capacity_in_bytes) {
-  Isolate* isolate = CcTest::i_isolate();
-  Heap* heap = isolate->heap();
-  OldSpace* old_space = new OldSpace(heap, OLD_SPACE, NOT_EXECUTABLE);
-  CHECK(old_space != nullptr);
-  CHECK(old_space->SetUp());
-  old_space->AllocateRawUnaligned(object_size).ToObjectChecked();
-  old_space->EmptyAllocationInfo();
-
-  intptr_t rest_capacity = old_space->accounting_stats_.Capacity() -
-                           old_space->accounting_stats_.Size();
-  intptr_t capacity_for_compaction_space =
-      rest_capacity / num_compaction_spaces;
-  int num_objects_in_compaction_space =
-      static_cast<int>(capacity_for_compaction_space) / object_size +
-      num_additional_objects;
-  CHECK_GT(num_objects_in_compaction_space, 0);
-  intptr_t initial_old_space_capacity = old_space->accounting_stats_.Capacity();
-
-  CompactionSpaceCollection** spaces =
-      InitializeCompactionSpaces(heap, num_compaction_spaces);
-  old_space->DivideUponCompactionSpaces(spaces, num_compaction_spaces,
-                                        capacity_for_compaction_space);
-
-  intptr_t compaction_capacity = 0;
-  intptr_t compaction_size = 0;
-  CompactionStats(spaces, OLD_SPACE, num_compaction_spaces,
-                  &compaction_capacity, &compaction_size);
-
-  intptr_t old_space_capacity = old_space->accounting_stats_.Capacity();
-  intptr_t old_space_size = old_space->accounting_stats_.Size();
-  // Compaction space memory is subtracted from the original space's capacity.
-  CHECK_EQ(old_space_capacity,
-           initial_old_space_capacity - compaction_capacity);
-  CHECK_EQ(compaction_size, 0);
-
-  AllocateInCompactionSpaces(spaces, OLD_SPACE, num_compaction_spaces,
-                             num_objects_in_compaction_space, object_size);
-
-  // Old space size and capacity should be the same as after dividing.
-  CHECK_EQ(old_space->accounting_stats_.Size(), old_space_size);
-  CHECK_EQ(old_space->accounting_stats_.Capacity(), old_space_capacity);
-
-  CompactionStats(spaces, OLD_SPACE, num_compaction_spaces,
-                  &compaction_capacity, &compaction_size);
-  MergeCompactionSpaces(old_space, spaces, num_compaction_spaces);
-
-  CHECK_EQ(old_space->accounting_stats_.Capacity(),
-           old_space_capacity + compaction_capacity);
-  CHECK_EQ(old_space->accounting_stats_.Size(),
-           old_space_size + compaction_size);
-  // We check against the expected end capacity.
-  CHECK_EQ(old_space->accounting_stats_.Capacity(),
-           initial_old_space_capacity + additional_capacity_in_bytes);
-
-  DestroyCompactionSpaces(spaces, num_compaction_spaces);
-  delete old_space;
-}
-
-
-HEAP_TEST(CompactionSpaceDivideSinglePage) {
-  const int kObjectSize = KB;
-  const int kCompactionSpaces = 4;
-  // Since the bound for objects is tight and the dividing is best effort, we
-  // subtract some objects to make sure we still fit in the initial page.
-  // A CHECK makes sure that the overall number of allocated objects stays
-  // > 0.
-  const int kAdditionalObjects = -10;
-  const int kAdditionalCapacityRequired = 0;
-  TestCompactionSpaceDivide(kAdditionalObjects, kObjectSize, kCompactionSpaces,
-                            kAdditionalCapacityRequired);
-}
-
-
-HEAP_TEST(CompactionSpaceDivideMultiplePages) {
-  const int kObjectSize = KB;
-  const int kCompactionSpaces = 4;
-  // Allocate half a page of objects to ensure that we need one more page per
-  // compaction space.
-  const int kAdditionalObjects = (Page::kPageSize / kObjectSize / 2);
-  const int kAdditionalCapacityRequired =
-      Page::kAllocatableMemory * kCompactionSpaces;
-  TestCompactionSpaceDivide(kAdditionalObjects, kObjectSize, kCompactionSpaces,
-                            kAdditionalCapacityRequired);
-}
-
-
 TEST(LargeObjectSpace) {
   v8::V8::Initialize();
 
@@ -744,50 +514,6 @@
   CHECK(isolate->heap()->lo_space()->IsEmpty());
 }
 
-
-UNINITIALIZED_TEST(NewSpaceGrowsToTargetCapacity) {
-  FLAG_target_semi_space_size = 2 * (Page::kPageSize / MB);
-  if (FLAG_optimize_for_size) return;
-
-  v8::Isolate::CreateParams create_params;
-  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
-  v8::Isolate* isolate = v8::Isolate::New(create_params);
-  {
-    v8::Isolate::Scope isolate_scope(isolate);
-    v8::HandleScope handle_scope(isolate);
-    v8::Context::New(isolate)->Enter();
-
-    Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
-
-    NewSpace* new_space = i_isolate->heap()->new_space();
-
-    // This test doesn't work if we start with a non-default new space
-    // configuration.
-    if (new_space->InitialTotalCapacity() == Page::kPageSize) {
-      CHECK_EQ(new_space->CommittedMemory(), new_space->InitialTotalCapacity());
-
-      // Fill up the first (and only) page of the semi space.
-      FillCurrentPage(new_space);
-
-      // Try to allocate out of the new space. A new page should be added and
-      // the
-      // allocation should succeed.
-      v8::internal::AllocationResult allocation =
-          new_space->AllocateRawUnaligned(80);
-      CHECK(!allocation.IsRetry());
-      CHECK_EQ(new_space->CommittedMemory(), 2 * Page::kPageSize);
-
-      // Turn the allocation into a proper object so isolate teardown won't
-      // crash.
-      HeapObject* free_space = NULL;
-      CHECK(allocation.To(&free_space));
-      new_space->heap()->CreateFillerObjectAt(free_space->address(), 80);
-    }
-  }
-  isolate->Dispose();
-}
-
-
 static HeapObject* AllocateUnaligned(NewSpace* space, int size) {
   AllocationResult allocation = space->AllocateRawUnaligned(size);
   CHECK(!allocation.IsRetry());
@@ -797,10 +523,27 @@
   return filler;
 }
 
-class Observer : public InlineAllocationObserver {
+static HeapObject* AllocateUnaligned(PagedSpace* space, int size) {
+  AllocationResult allocation = space->AllocateRaw(size, kDoubleUnaligned);
+  CHECK(!allocation.IsRetry());
+  HeapObject* filler = NULL;
+  CHECK(allocation.To(&filler));
+  space->heap()->CreateFillerObjectAt(filler->address(), size);
+  return filler;
+}
+
+static HeapObject* AllocateUnaligned(LargeObjectSpace* space, int size) {
+  AllocationResult allocation = space->AllocateRaw(size, EXECUTABLE);
+  CHECK(!allocation.IsRetry());
+  HeapObject* filler = NULL;
+  CHECK(allocation.To(&filler));
+  return filler;
+}
+
+class Observer : public AllocationObserver {
  public:
   explicit Observer(intptr_t step_size)
-      : InlineAllocationObserver(step_size), count_(0) {}
+      : AllocationObserver(step_size), count_(0) {}
 
   void Step(int bytes_allocated, Address, size_t) override { count_++; }
 
@@ -810,8 +553,76 @@
   int count_;
 };
 
+template <typename T>
+void testAllocationObserver(Isolate* i_isolate, T* space) {
+  Observer observer1(128);
+  space->AddAllocationObserver(&observer1);
 
-UNINITIALIZED_TEST(InlineAllocationObserver) {
+  // The observer should not get notified if we have only allocated less than
+  // 128 bytes.
+  AllocateUnaligned(space, 64);
+  CHECK_EQ(observer1.count(), 0);
+
+  // The observer should get called when we have allocated exactly 128 bytes.
+  AllocateUnaligned(space, 64);
+  CHECK_EQ(observer1.count(), 1);
+
+  // Another >128 bytes should get another notification.
+  AllocateUnaligned(space, 136);
+  CHECK_EQ(observer1.count(), 2);
+
+  // Allocating a large object should get only one notification.
+  AllocateUnaligned(space, 1024);
+  CHECK_EQ(observer1.count(), 3);
+
+  // Allocating another 2048 bytes in small objects should get 16
+  // notifications.
+  for (int i = 0; i < 64; ++i) {
+    AllocateUnaligned(space, 32);
+  }
+  CHECK_EQ(observer1.count(), 19);
+
+  // Multiple observers should work.
+  Observer observer2(96);
+  space->AddAllocationObserver(&observer2);
+
+  AllocateUnaligned(space, 2048);
+  CHECK_EQ(observer1.count(), 20);
+  CHECK_EQ(observer2.count(), 1);
+
+  AllocateUnaligned(space, 104);
+  CHECK_EQ(observer1.count(), 20);
+  CHECK_EQ(observer2.count(), 2);
+
+  // Callback should stop getting called after an observer is removed.
+  space->RemoveAllocationObserver(&observer1);
+
+  AllocateUnaligned(space, 384);
+  CHECK_EQ(observer1.count(), 20);  // no more notifications.
+  CHECK_EQ(observer2.count(), 3);   // this one is still active.
+
+  // Ensure that PauseInlineAllocationObserversScope work correctly.
+  AllocateUnaligned(space, 48);
+  CHECK_EQ(observer2.count(), 3);
+  {
+    PauseAllocationObserversScope pause_observers(i_isolate->heap());
+    CHECK_EQ(observer2.count(), 3);
+    AllocateUnaligned(space, 384);
+    CHECK_EQ(observer2.count(), 3);
+  }
+  CHECK_EQ(observer2.count(), 3);
+  // Coupled with the 48 bytes allocated before the pause, another 48 bytes
+  // allocated here should trigger a notification.
+  AllocateUnaligned(space, 48);
+  CHECK_EQ(observer2.count(), 4);
+
+  space->RemoveAllocationObserver(&observer2);
+  AllocateUnaligned(space, 384);
+  CHECK_EQ(observer1.count(), 20);
+  CHECK_EQ(observer2.count(), 4);
+}
+
+UNINITIALIZED_TEST(AllocationObserver) {
   v8::Isolate::CreateParams create_params;
   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   v8::Isolate* isolate = v8::Isolate::New(create_params);
@@ -822,73 +633,13 @@
 
     Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
 
-    NewSpace* new_space = i_isolate->heap()->new_space();
-
-    Observer observer1(128);
-    new_space->AddInlineAllocationObserver(&observer1);
-
-    // The observer should not get notified if we have only allocated less than
-    // 128 bytes.
-    AllocateUnaligned(new_space, 64);
-    CHECK_EQ(observer1.count(), 0);
-
-    // The observer should get called when we have allocated exactly 128 bytes.
-    AllocateUnaligned(new_space, 64);
-    CHECK_EQ(observer1.count(), 1);
-
-    // Another >128 bytes should get another notification.
-    AllocateUnaligned(new_space, 136);
-    CHECK_EQ(observer1.count(), 2);
-
-    // Allocating a large object should get only one notification.
-    AllocateUnaligned(new_space, 1024);
-    CHECK_EQ(observer1.count(), 3);
-
-    // Allocating another 2048 bytes in small objects should get 16
-    // notifications.
-    for (int i = 0; i < 64; ++i) {
-      AllocateUnaligned(new_space, 32);
-    }
-    CHECK_EQ(observer1.count(), 19);
-
-    // Multiple observers should work.
-    Observer observer2(96);
-    new_space->AddInlineAllocationObserver(&observer2);
-
-    AllocateUnaligned(new_space, 2048);
-    CHECK_EQ(observer1.count(), 20);
-    CHECK_EQ(observer2.count(), 1);
-
-    AllocateUnaligned(new_space, 104);
-    CHECK_EQ(observer1.count(), 20);
-    CHECK_EQ(observer2.count(), 2);
-
-    // Callback should stop getting called after an observer is removed.
-    new_space->RemoveInlineAllocationObserver(&observer1);
-
-    AllocateUnaligned(new_space, 384);
-    CHECK_EQ(observer1.count(), 20);  // no more notifications.
-    CHECK_EQ(observer2.count(), 3);   // this one is still active.
-
-    // Ensure that PauseInlineAllocationObserversScope work correctly.
-    AllocateUnaligned(new_space, 48);
-    CHECK_EQ(observer2.count(), 3);
-    {
-      PauseInlineAllocationObserversScope pause_observers(new_space);
-      CHECK_EQ(observer2.count(), 3);
-      AllocateUnaligned(new_space, 384);
-      CHECK_EQ(observer2.count(), 3);
-    }
-    CHECK_EQ(observer2.count(), 3);
-    // Coupled with the 48 bytes allocated before the pause, another 48 bytes
-    // allocated here should trigger a notification.
-    AllocateUnaligned(new_space, 48);
-    CHECK_EQ(observer2.count(), 4);
-
-    new_space->RemoveInlineAllocationObserver(&observer2);
-    AllocateUnaligned(new_space, 384);
-    CHECK_EQ(observer1.count(), 20);
-    CHECK_EQ(observer2.count(), 4);
+    testAllocationObserver<NewSpace>(i_isolate, i_isolate->heap()->new_space());
+    // Old space is used but the code path is shared for all
+    // classes inheriting from PagedSpace.
+    testAllocationObserver<PagedSpace>(i_isolate,
+                                       i_isolate->heap()->old_space());
+    testAllocationObserver<LargeObjectSpace>(i_isolate,
+                                             i_isolate->heap()->lo_space());
   }
   isolate->Dispose();
 }
@@ -908,16 +659,16 @@
     NewSpace* new_space = i_isolate->heap()->new_space();
 
     Observer observer1(512);
-    new_space->AddInlineAllocationObserver(&observer1);
+    new_space->AddAllocationObserver(&observer1);
     Observer observer2(576);
-    new_space->AddInlineAllocationObserver(&observer2);
+    new_space->AddAllocationObserver(&observer2);
 
     for (int i = 0; i < 512; ++i) {
       AllocateUnaligned(new_space, 32);
     }
 
-    new_space->RemoveInlineAllocationObserver(&observer1);
-    new_space->RemoveInlineAllocationObserver(&observer2);
+    new_space->RemoveAllocationObserver(&observer1);
+    new_space->RemoveAllocationObserver(&observer2);
 
     CHECK_EQ(observer1.count(), 32);
     CHECK_EQ(observer2.count(), 28);
diff --git a/test/cctest/interpreter/bytecode-expectations-printer.cc b/test/cctest/interpreter/bytecode-expectations-printer.cc
new file mode 100644
index 0000000..d5e0456
--- /dev/null
+++ b/test/cctest/interpreter/bytecode-expectations-printer.cc
@@ -0,0 +1,301 @@
+// Copyright 2016 the V8 project 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/bytecode-expectations-printer.h"
+
+#include <iostream>
+#include <vector>
+
+#include "include/libplatform/libplatform.h"
+#include "include/v8.h"
+
+#include "src/base/logging.h"
+#include "src/base/smart-pointers.h"
+#include "src/compiler.h"
+
+#include "src/interpreter/bytecode-array-iterator.h"
+#include "src/interpreter/bytecode-generator.h"
+#include "src/interpreter/bytecodes.h"
+#include "src/interpreter/interpreter.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+// static
+const char* const BytecodeExpectationsPrinter::kDefaultTopFunctionName =
+    "__genbckexp_wrapper__";
+
+v8::Local<v8::String> BytecodeExpectationsPrinter::V8StringFromUTF8(
+    const char* data) const {
+  return v8::String::NewFromUtf8(isolate_, data, v8::NewStringType::kNormal)
+      .ToLocalChecked();
+}
+
+std::string BytecodeExpectationsPrinter::WrapCodeInFunction(
+    const char* function_name, const std::string& function_body) const {
+  std::ostringstream program_stream;
+  program_stream << "function " << function_name << "() {" << function_body
+                 << "}\n"
+                 << function_name << "();";
+
+  return program_stream.str();
+}
+
+v8::Local<v8::Script> BytecodeExpectationsPrinter::Compile(
+    const char* program) const {
+  v8::Local<v8::String> source = V8StringFromUTF8(program);
+  return v8::Script::Compile(isolate_->GetCurrentContext(), source)
+      .ToLocalChecked();
+}
+
+void BytecodeExpectationsPrinter::Run(v8::Local<v8::Script> script) const {
+  (void)script->Run(isolate_->GetCurrentContext());
+}
+
+i::Handle<v8::internal::BytecodeArray>
+BytecodeExpectationsPrinter::GetBytecodeArrayForGlobal(
+    const char* global_name) const {
+  const v8::Local<v8::Context>& context = isolate_->GetCurrentContext();
+  v8::Local<v8::String> v8_global_name = V8StringFromUTF8(global_name);
+  v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+      context->Global()->Get(context, v8_global_name).ToLocalChecked());
+  i::Handle<i::JSFunction> js_function =
+      i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function));
+
+  i::Handle<i::BytecodeArray> bytecodes =
+      i::handle(js_function->shared()->bytecode_array(), i_isolate());
+
+  return bytecodes;
+}
+
+i::Handle<i::BytecodeArray>
+BytecodeExpectationsPrinter::GetBytecodeArrayForScript(
+    v8::Local<v8::Script> script) const {
+  i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*script);
+  return i::handle(js_function->shared()->bytecode_array(), i_isolate());
+}
+
+void BytecodeExpectationsPrinter::PrintEscapedString(
+    std::ostream& stream, const std::string& string) const {
+  for (char c : string) {
+    switch (c) {
+      case '"':
+        stream << "\\\"";
+        break;
+      case '\\':
+        stream << "\\\\";
+        break;
+      default:
+        stream << c;
+        break;
+    }
+  }
+}
+
+void BytecodeExpectationsPrinter::PrintBytecodeOperand(
+    std::ostream& stream, const BytecodeArrayIterator& bytecode_iter,
+    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);
+
+  const char* size_tag;
+  switch (op_size) {
+    case OperandSize::kByte:
+      size_tag = "8";
+      break;
+    case OperandSize::kShort:
+      size_tag = "16";
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+
+  if (Bytecodes::IsRegisterOperandType(op_type)) {
+    Register register_value = bytecode_iter.GetRegisterOperand(op_index);
+    stream << 'R';
+    if (op_size != OperandSize::kByte) stream << size_tag;
+    if (register_value.is_new_target()) {
+      stream << "(new_target)";
+    } else if (register_value.is_current_context()) {
+      stream << "(context)";
+    } else if (register_value.is_function_closure()) {
+      stream << "(closure)";
+    } else if (register_value.is_parameter()) {
+      int parameter_index = register_value.ToParameterIndex(parameter_count);
+      if (parameter_index == 0) {
+        stream << "(this)";
+      } else {
+        stream << "(arg" << (parameter_index - 1) << ')';
+      }
+    } else {
+      stream << '(' << register_value.index() << ')';
+    }
+  } else {
+    stream << 'U' << size_tag << '(';
+
+    if (Bytecodes::IsImmediateOperandType(op_type)) {
+      // We need a cast, otherwise the result is printed as char.
+      stream << static_cast<int>(bytecode_iter.GetImmediateOperand(op_index));
+    } else if (Bytecodes::IsRegisterCountOperandType(op_type)) {
+      stream << bytecode_iter.GetRegisterCountOperand(op_index);
+    } else if (Bytecodes::IsIndexOperandType(op_type)) {
+      stream << bytecode_iter.GetIndexOperand(op_index);
+    } else {
+      UNREACHABLE();
+    }
+
+    stream << ')';
+  }
+}
+
+void BytecodeExpectationsPrinter::PrintBytecode(
+    std::ostream& stream, const BytecodeArrayIterator& bytecode_iter,
+    int parameter_count) const {
+  Bytecode bytecode = bytecode_iter.current_bytecode();
+
+  stream << "B(" << Bytecodes::ToString(bytecode) << ')';
+
+  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,
+                         parameter_count);
+  }
+}
+
+void BytecodeExpectationsPrinter::PrintV8String(std::ostream& stream,
+                                                i::String* string) const {
+  stream << '"';
+  for (int i = 0, length = string->length(); i < length; ++i) {
+    stream << i::AsEscapedUC16ForJSON(string->Get(i));
+  }
+  stream << '"';
+}
+
+void BytecodeExpectationsPrinter::PrintConstant(
+    std::ostream& stream, i::Handle<i::Object> constant) const {
+  switch (const_pool_type_) {
+    case ConstantPoolType::kString:
+      CHECK(constant->IsString());
+      PrintV8String(stream, i::String::cast(*constant));
+      break;
+    case ConstantPoolType::kNumber:
+      if (constant->IsSmi()) {
+        i::Smi::cast(*constant)->SmiPrint(stream);
+      } else if (constant->IsHeapNumber()) {
+        i::HeapNumber::cast(*constant)->HeapNumberPrint(stream);
+      } else {
+        UNREACHABLE();
+      }
+      break;
+    case ConstantPoolType::kMixed:
+      if (constant->IsSmi()) {
+        stream << "kInstanceTypeDontCare";
+      } else {
+        stream << "InstanceType::"
+               << i::HeapObject::cast(*constant)->map()->instance_type();
+      }
+      break;
+    case ConstantPoolType::kUnknown:
+    default:
+      UNREACHABLE();
+      return;
+  }
+}
+
+void BytecodeExpectationsPrinter::PrintFrameSize(
+    std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+  const int kPointerSize = sizeof(void*);
+  int frame_size = bytecode_array->frame_size();
+
+  DCHECK_EQ(frame_size % kPointerSize, 0);
+  stream << "frame size: " << frame_size / kPointerSize;
+  if (frame_size > 0) stream << "  # in multiples of sizeof(void*)";
+  stream << "\nparameter count: " << bytecode_array->parameter_count() << '\n';
+}
+
+void BytecodeExpectationsPrinter::PrintBytecodeSequence(
+    std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+  stream << "bytecodes: [\n";
+  BytecodeArrayIterator bytecode_iter(bytecode_array);
+  for (; !bytecode_iter.done(); bytecode_iter.Advance()) {
+    stream << "  ";
+    PrintBytecode(stream, bytecode_iter, bytecode_array->parameter_count());
+    stream << ",\n";
+  }
+  stream << "]\n";
+}
+
+void BytecodeExpectationsPrinter::PrintConstantPool(
+    std::ostream& stream, i::FixedArray* constant_pool) const {
+  stream << "constant pool: [\n";
+  int num_constants = constant_pool->length();
+  if (num_constants > 0) {
+    for (int i = 0; i < num_constants; ++i) {
+      stream << "  ";
+      PrintConstant(stream, i::FixedArray::get(constant_pool, i, i_isolate()));
+      stream << ",\n";
+    }
+  }
+  stream << "]\n";
+}
+
+void BytecodeExpectationsPrinter::PrintCodeSnippet(
+    std::ostream& stream, const std::string& body) const {
+  stream << "snippet: \"\n";
+  std::stringstream body_stream(body);
+  std::string body_line;
+  while (std::getline(body_stream, body_line)) {
+    stream << "  ";
+    PrintEscapedString(stream, body_line);
+    stream << '\n';
+  }
+  stream << "\"\n";
+}
+
+void BytecodeExpectationsPrinter::PrintHandlers(
+    std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+  stream << "handlers: [\n";
+  HandlerTable* table = HandlerTable::cast(bytecode_array->handler_table());
+  for (int i = 0, num_entries = table->NumberOfRangeEntries(); i < num_entries;
+       ++i) {
+    stream << "  [" << table->GetRangeStart(i) << ", " << table->GetRangeEnd(i)
+           << ", " << table->GetRangeHandler(i) << "],\n";
+  }
+  stream << "]\n";
+}
+
+void BytecodeExpectationsPrinter::PrintBytecodeArray(
+    std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+  PrintFrameSize(stream, bytecode_array);
+  PrintBytecodeSequence(stream, bytecode_array);
+  PrintConstantPool(stream, bytecode_array->constant_pool());
+  PrintHandlers(stream, bytecode_array);
+}
+
+void BytecodeExpectationsPrinter::PrintExpectation(
+    std::ostream& stream, const std::string& snippet) const {
+  std::string source_code =
+      wrap_ ? WrapCodeInFunction(test_function_name_.c_str(), snippet)
+            : snippet;
+
+  v8::Local<v8::Script> script = Compile(source_code.c_str());
+
+  if (execute_) Run(script);
+
+  i::Handle<i::BytecodeArray> bytecode_array =
+      top_level_ ? GetBytecodeArrayForScript(script)
+                 : GetBytecodeArrayForGlobal(test_function_name_.c_str());
+
+  stream << "---\n";
+  PrintCodeSnippet(stream, snippet);
+  PrintBytecodeArray(stream, bytecode_array);
+  stream << '\n';
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/interpreter/bytecode-expectations-printer.h b/test/cctest/interpreter/bytecode-expectations-printer.h
new file mode 100644
index 0000000..236a7d4
--- /dev/null
+++ b/test/cctest/interpreter/bytecode-expectations-printer.h
@@ -0,0 +1,119 @@
+// Copyright 2016 the V8 project 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_BYTECODE_EXPECTATIONS_PRINTER_H_
+#define TEST_CCTEST_INTERPRETER_BYTECODE_EXPECTATIONS_PRINTER_H_
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "src/interpreter/bytecodes.h"
+#include "src/objects.h"
+
+namespace v8 {
+
+class Isolate;
+
+namespace internal {
+namespace interpreter {
+
+class BytecodeArrayIterator;
+
+class BytecodeExpectationsPrinter final {
+ public:
+  enum class ConstantPoolType {
+    kUnknown,
+    kString,
+    kNumber,
+    kMixed,
+  };
+
+  BytecodeExpectationsPrinter(v8::Isolate* i,
+                              ConstantPoolType t = ConstantPoolType::kMixed)
+      : isolate_(i),
+        const_pool_type_(t),
+        execute_(true),
+        wrap_(true),
+        test_function_name_(kDefaultTopFunctionName) {}
+
+  void PrintExpectation(std::ostream& stream,  // NOLINT
+                        const std::string& snippet) const;
+
+  void set_constant_pool_type(ConstantPoolType const_pool_type) {
+    const_pool_type_ = const_pool_type;
+  }
+  ConstantPoolType const_pool_type() const { return const_pool_type_; }
+
+  void set_execute(bool execute) { execute_ = execute; }
+  bool execute() const { return execute_; }
+
+  void set_wrap(bool wrap) { wrap_ = wrap; }
+  bool wrap() const { return wrap_; }
+
+  void set_top_level(bool top_level) { top_level_ = top_level; }
+  bool top_level() const { return top_level_; }
+
+  void set_test_function_name(const std::string& test_function_name) {
+    test_function_name_ = test_function_name;
+  }
+  std::string test_function_name() const { return test_function_name_; }
+
+ private:
+  void PrintEscapedString(std::ostream& stream,  // NOLINT
+                          const std::string& string) const;
+  void PrintBytecodeOperand(std::ostream& stream,  // NOLINT
+                            const BytecodeArrayIterator& bytecode_iter,
+                            const Bytecode& bytecode, int op_index,
+                            int parameter_count) const;
+  void PrintBytecode(std::ostream& stream,  // NOLINT
+                     const BytecodeArrayIterator& bytecode_iter,
+                     int parameter_count) const;
+  void PrintV8String(std::ostream& stream,  // NOLINT
+                     i::String* string) const;
+  void PrintConstant(std::ostream& stream,  // NOLINT
+                     i::Handle<i::Object> constant) const;
+  void PrintFrameSize(std::ostream& stream,  // NOLINT
+                      i::Handle<i::BytecodeArray> bytecode_array) const;
+  void PrintBytecodeSequence(std::ostream& stream,  // NOLINT
+                             i::Handle<i::BytecodeArray> bytecode_array) const;
+  void PrintConstantPool(std::ostream& stream,  // NOLINT
+                         i::FixedArray* constant_pool) const;
+  void PrintCodeSnippet(std::ostream& stream,  // NOLINT
+                        const std::string& body) const;
+  void PrintBytecodeArray(std::ostream& stream,  // NOLINT
+                          i::Handle<i::BytecodeArray> bytecode_array) const;
+  void PrintHandlers(std::ostream& stream,  // NOLINT
+                     i::Handle<i::BytecodeArray> bytecode_array) const;
+
+  v8::Local<v8::String> V8StringFromUTF8(const char* data) const;
+  std::string WrapCodeInFunction(const char* function_name,
+                                 const std::string& function_body) const;
+
+  v8::Local<v8::Script> Compile(const char* program) const;
+  void Run(v8::Local<v8::Script> script) const;
+  i::Handle<i::BytecodeArray> GetBytecodeArrayForGlobal(
+      const char* global_name) const;
+  i::Handle<v8::internal::BytecodeArray> GetBytecodeArrayForScript(
+      v8::Local<v8::Script> script) const;
+
+  i::Isolate* i_isolate() const {
+    return reinterpret_cast<i::Isolate*>(isolate_);
+  }
+
+  v8::Isolate* isolate_;
+  ConstantPoolType const_pool_type_;
+  bool execute_;
+  bool wrap_;
+  bool top_level_;
+  std::string test_function_name_;
+
+  static const char* const kDefaultTopFunctionName;
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // TEST_CCTEST_INTERPRETER_BYTECODE_EXPECTATIONS_PRINTER_H_
diff --git a/test/cctest/interpreter/generate-bytecode-expectations.cc b/test/cctest/interpreter/generate-bytecode-expectations.cc
new file mode 100644
index 0000000..567aa41
--- /dev/null
+++ b/test/cctest/interpreter/generate-bytecode-expectations.cc
@@ -0,0 +1,469 @@
+// Copyright 2016 the V8 project 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 <cstring>
+#include <fstream>
+
+#include "test/cctest/interpreter/bytecode-expectations-printer.h"
+
+#include "include/libplatform/libplatform.h"
+#include "include/v8.h"
+
+#include "src/base/logging.h"
+#include "src/base/smart-pointers.h"
+#include "src/compiler.h"
+#include "src/interpreter/interpreter.h"
+
+using v8::internal::interpreter::BytecodeExpectationsPrinter;
+
+namespace {
+
+class ProgramOptions final {
+ public:
+  static ProgramOptions FromCommandLine(int argc, char** argv);
+
+  ProgramOptions()
+      : parsing_failed_(false),
+        print_help_(false),
+        read_raw_js_snippet_(false),
+        read_from_stdin_(false),
+        rebaseline_(false),
+        wrap_(true),
+        execute_(true),
+        top_level_(false),
+        legacy_const_(false),
+        do_expressions_(false),
+        const_pool_type_(
+            BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {}
+
+  bool Validate() const;
+  void UpdateFromHeader(std::istream& stream);   // NOLINT
+  void PrintHeader(std::ostream& stream) const;  // NOLINT
+
+  bool parsing_failed() const { return parsing_failed_; }
+  bool print_help() const { return print_help_; }
+  bool read_raw_js_snippet() const { return read_raw_js_snippet_; }
+  bool read_from_stdin() const { return read_from_stdin_; }
+  bool write_to_stdout() const {
+    return output_filename_.empty() && !rebaseline_;
+  }
+  bool rebaseline() const { return rebaseline_; }
+  bool wrap() const { return wrap_; }
+  bool execute() const { return execute_; }
+  bool top_level() const { return top_level_; }
+  bool legacy_const() const { return legacy_const_; }
+  bool do_expressions() const { return do_expressions_; }
+  BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const {
+    return const_pool_type_;
+  }
+  std::string input_filename() const { return input_filename_; }
+  std::string output_filename() const { return output_filename_; }
+  std::string test_function_name() const { return test_function_name_; }
+
+ private:
+  bool parsing_failed_;
+  bool print_help_;
+  bool read_raw_js_snippet_;
+  bool read_from_stdin_;
+  bool rebaseline_;
+  bool wrap_;
+  bool execute_;
+  bool top_level_;
+  bool legacy_const_;
+  bool do_expressions_;
+  BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_;
+  std::string input_filename_;
+  std::string output_filename_;
+  std::string test_function_name_;
+};
+
+class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator {
+ public:
+  void* Allocate(size_t length) override {
+    void* data = AllocateUninitialized(length);
+    if (data != nullptr) memset(data, 0, length);
+    return data;
+  }
+  void* AllocateUninitialized(size_t length) override { return malloc(length); }
+  void Free(void* data, size_t) override { free(data); }
+};
+
+class V8InitializationScope final {
+ public:
+  explicit V8InitializationScope(const char* exec_path);
+  ~V8InitializationScope();
+
+  v8::Platform* platform() const { return platform_.get(); }
+  v8::Isolate* isolate() const { return isolate_; }
+
+ private:
+  v8::base::SmartPointer<v8::Platform> platform_;
+  v8::Isolate* isolate_;
+
+  DISALLOW_COPY_AND_ASSIGN(V8InitializationScope);
+};
+
+BytecodeExpectationsPrinter::ConstantPoolType ParseConstantPoolType(
+    const char* type_string) {
+  if (strcmp(type_string, "number") == 0) {
+    return BytecodeExpectationsPrinter::ConstantPoolType::kNumber;
+  } else if (strcmp(type_string, "string") == 0) {
+    return BytecodeExpectationsPrinter::ConstantPoolType::kString;
+  } else if (strcmp(type_string, "mixed") == 0) {
+    return BytecodeExpectationsPrinter::ConstantPoolType::kMixed;
+  }
+  return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown;
+}
+
+const char* ConstantPoolTypeToString(
+    BytecodeExpectationsPrinter::ConstantPoolType type) {
+  switch (type) {
+    case BytecodeExpectationsPrinter::ConstantPoolType::kNumber:
+      return "number";
+    case BytecodeExpectationsPrinter::ConstantPoolType::kMixed:
+      return "mixed";
+    case BytecodeExpectationsPrinter::ConstantPoolType::kString:
+      return "string";
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+}
+
+bool ParseBoolean(const char* string) {
+  if (strcmp(string, "yes") == 0) {
+    return true;
+  } else if (strcmp(string, "no") == 0) {
+    return false;
+  } else {
+    UNREACHABLE();
+    return false;
+  }
+}
+
+const char* BooleanToString(bool value) { return value ? "yes" : "no"; }
+
+// static
+ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) {
+  ProgramOptions options;
+
+  for (int i = 1; i < argc; ++i) {
+    if (strcmp(argv[i], "--help") == 0) {
+      options.print_help_ = true;
+    } else if (strcmp(argv[i], "--raw-js") == 0) {
+      options.read_raw_js_snippet_ = true;
+    } else if (strncmp(argv[i], "--pool-type=", 12) == 0) {
+      options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12);
+    } else if (strcmp(argv[i], "--stdin") == 0) {
+      options.read_from_stdin_ = true;
+    } else if (strcmp(argv[i], "--rebaseline") == 0) {
+      options.rebaseline_ = true;
+    } else if (strcmp(argv[i], "--no-wrap") == 0) {
+      options.wrap_ = false;
+    } else if (strcmp(argv[i], "--no-execute") == 0) {
+      options.execute_ = false;
+    } else if (strcmp(argv[i], "--top-level") == 0) {
+      options.top_level_ = true;
+    } else if (strcmp(argv[i], "--legacy-const") == 0) {
+      options.legacy_const_ = true;
+    } else if (strcmp(argv[i], "--do-expressions") == 0) {
+      options.do_expressions_ = true;
+    } else if (strncmp(argv[i], "--output=", 9) == 0) {
+      options.output_filename_ = argv[i] + 9;
+    } else if (strncmp(argv[i], "--test-function-name=", 21) == 0) {
+      options.test_function_name_ = argv[i] + 21;
+    } else if (strncmp(argv[i], "--", 2) != 0) {  // It doesn't start with --
+      if (!options.input_filename_.empty()) {
+        std::cerr << "ERROR: More than one input file specified\n";
+        options.parsing_failed_ = true;
+        break;
+      }
+      options.input_filename_ = argv[i];
+    } else {
+      std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n";
+      options.parsing_failed_ = true;
+      break;
+    }
+  }
+
+  return options;
+}
+
+bool ProgramOptions::Validate() const {
+  if (parsing_failed_) return false;
+  if (print_help_) return true;
+
+  if (const_pool_type_ ==
+      BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) {
+    std::cerr << "ERROR: Unknown constant pool type.\n";
+    return false;
+  }
+
+  if (!read_from_stdin_ && input_filename_.empty()) {
+    std::cerr << "ERROR: No input file specified.\n";
+    return false;
+  }
+
+  if (read_from_stdin_ && !input_filename_.empty()) {
+    std::cerr << "ERROR: Reading from stdin, but input files supplied.\n";
+    return false;
+  }
+
+  if (rebaseline_ && read_raw_js_snippet_) {
+    std::cerr << "ERROR: Cannot use --rebaseline on a raw JS snippet.\n";
+    return false;
+  }
+
+  if (top_level_ && !test_function_name_.empty()) {
+    std::cerr << "ERROR: test function name specified while processing "
+                 "top level code.\n";
+    return false;
+  }
+
+  return true;
+}
+
+void ProgramOptions::UpdateFromHeader(std::istream& stream) {
+  std::string line;
+
+  // Skip to the beginning of the options header
+  while (std::getline(stream, line)) {
+    if (line == "---") break;
+  }
+
+  while (std::getline(stream, line)) {
+    if (line.compare(0, 11, "pool type: ") == 0) {
+      const_pool_type_ = ParseConstantPoolType(line.c_str() + 11);
+    } else if (line.compare(0, 9, "execute: ") == 0) {
+      execute_ = ParseBoolean(line.c_str() + 9);
+    } else if (line.compare(0, 6, "wrap: ") == 0) {
+      wrap_ = ParseBoolean(line.c_str() + 6);
+    } else if (line.compare(0, 20, "test function name: ") == 0) {
+      test_function_name_ = line.c_str() + 20;
+    } else if (line.compare(0, 11, "top level: ") == 0) {
+      top_level_ = ParseBoolean(line.c_str() + 11);
+    } else if (line.compare(0, 14, "legacy const: ") == 0) {
+      legacy_const_ = ParseBoolean(line.c_str() + 14);
+    } else if (line.compare(0, 16, "do expressions: ") == 0) {
+      do_expressions_ = ParseBoolean(line.c_str() + 16);
+    } else if (line == "---") {
+      break;
+    } else if (line.empty()) {
+      continue;
+    } else {
+      UNREACHABLE();
+      return;
+    }
+  }
+}
+
+void ProgramOptions::PrintHeader(std::ostream& stream) const {  // NOLINT
+  stream << "---"
+            "\npool type: "
+         << ConstantPoolTypeToString(const_pool_type_)
+         << "\nexecute: " << BooleanToString(execute_)
+         << "\nwrap: " << BooleanToString(wrap_);
+
+  if (!test_function_name_.empty()) {
+    stream << "\ntest function name: " << test_function_name_;
+  }
+
+  if (top_level_) stream << "\ntop level: yes";
+  if (legacy_const_) stream << "\nlegacy const: yes";
+  if (do_expressions_) stream << "\ndo expressions: yes";
+
+  stream << "\n\n";
+}
+
+V8InitializationScope::V8InitializationScope(const char* exec_path)
+    : platform_(v8::platform::CreateDefaultPlatform()) {
+  i::FLAG_ignition = true;
+  i::FLAG_always_opt = false;
+  i::FLAG_allow_natives_syntax = true;
+
+  v8::V8::InitializeICU();
+  v8::V8::InitializeExternalStartupData(exec_path);
+  v8::V8::InitializePlatform(platform_.get());
+  v8::V8::Initialize();
+
+  ArrayBufferAllocator allocator;
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = &allocator;
+
+  isolate_ = v8::Isolate::New(create_params);
+}
+
+V8InitializationScope::~V8InitializationScope() {
+  isolate_->Dispose();
+  v8::V8::Dispose();
+  v8::V8::ShutdownPlatform();
+}
+
+std::string ReadRawJSSnippet(std::istream& stream) {  // NOLINT
+  std::stringstream body_buffer;
+  CHECK(body_buffer << stream.rdbuf());
+  return body_buffer.str();
+}
+
+bool ReadNextSnippet(std::istream& stream, std::string* string_out) {  // NOLINT
+  std::string line;
+  bool found_begin_snippet = false;
+  string_out->clear();
+  while (std::getline(stream, line)) {
+    if (line == "snippet: \"") {
+      found_begin_snippet = true;
+      continue;
+    }
+    if (!found_begin_snippet) continue;
+    if (line == "\"") return true;
+    CHECK_GE(line.size(), 2u);  // We should have the indent
+    string_out->append(line.begin() + 2, line.end());
+    *string_out += '\n';
+  }
+  return false;
+}
+
+std::string UnescapeString(const std::string& escaped_string) {
+  std::string unescaped_string;
+  bool previous_was_backslash = false;
+  for (char c : escaped_string) {
+    if (previous_was_backslash) {
+      // If it was not an escape sequence, emit the previous backslash
+      if (c != '\\' && c != '"') unescaped_string += '\\';
+      unescaped_string += c;
+      previous_was_backslash = false;
+    } else {
+      if (c == '\\') {
+        previous_was_backslash = true;
+        // Defer emission to the point where we can check if it was an escape.
+      } else {
+        unescaped_string += c;
+      }
+    }
+  }
+  return unescaped_string;
+}
+
+void ExtractSnippets(std::vector<std::string>* snippet_list,
+                     std::istream& body_stream,  // NOLINT
+                     bool read_raw_js_snippet) {
+  if (read_raw_js_snippet) {
+    snippet_list->push_back(ReadRawJSSnippet(body_stream));
+  } else {
+    std::string snippet;
+    while (ReadNextSnippet(body_stream, &snippet)) {
+      snippet_list->push_back(UnescapeString(snippet));
+    }
+  }
+}
+
+void GenerateExpectationsFile(std::ostream& stream,  // NOLINT
+                              const std::vector<std::string>& snippet_list,
+                              const ProgramOptions& options,
+                              const char* exec_path) {
+  V8InitializationScope platform(exec_path);
+  {
+    v8::Isolate::Scope isolate_scope(platform.isolate());
+    v8::HandleScope handle_scope(platform.isolate());
+    v8::Local<v8::Context> context = v8::Context::New(platform.isolate());
+    v8::Context::Scope context_scope(context);
+
+    BytecodeExpectationsPrinter printer(platform.isolate(),
+                                        options.const_pool_type());
+    printer.set_wrap(options.wrap());
+    printer.set_execute(options.execute());
+    printer.set_top_level(options.top_level());
+    if (!options.test_function_name().empty()) {
+      printer.set_test_function_name(options.test_function_name());
+    }
+
+    if (options.legacy_const()) i::FLAG_legacy_const = true;
+    if (options.do_expressions()) i::FLAG_harmony_do_expressions = true;
+
+    stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n";
+    options.PrintHeader(stream);
+    for (const std::string& snippet : snippet_list) {
+      printer.PrintExpectation(stream, snippet);
+    }
+  }
+}
+
+void PrintUsage(const char* exec_path) {
+  std::cerr
+      << "\nUsage: " << exec_path
+      << " [OPTIONS]... [INPUT FILE]\n\n"
+         "Options:\n"
+         "  --help    Print this help message.\n"
+         "  --raw-js  Read raw JavaScript, instead of the output format.\n"
+         "  --stdin   Read from standard input instead of file.\n"
+         "  --rebaseline  Rebaseline input snippet file.\n"
+         "  --no-wrap     Do not wrap the snippet in a function.\n"
+         "  --no-execute  Do not execute after compilation.\n"
+         "  --test-function-name=foo  "
+         "Specify the name of the test function.\n"
+         "  --top-level   Process top level code, not the top-level function."
+         "  --legacy-const  Enable legacy_const flag.\n"
+         "  --do-expressions  Enable harmony_do_expressions flag.\n"
+         "  --output=file.name\n"
+         "      Specify the output file. If not specified, output goes to "
+         "stdout.\n"
+         "  --pool-type=(number|string|mixed)\n"
+         "      Specify the type of the entries in the constant pool "
+         "(default: mixed).\n"
+         "\n"
+         "When using --rebaseline, flags --no-wrap, --no-execute, "
+         "--test-function-name\nand --pool-type will be overridden by the "
+         "options specified in the input file\nheader.\n\n"
+         "Each raw JavaScript file is interpreted as a single snippet.\n\n"
+         "This tool is intended as a help in writing tests.\n"
+         "Please, DO NOT blindly copy and paste the output "
+         "into the test suite.\n";
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv);
+
+  if (!options.Validate() || options.print_help()) {
+    PrintUsage(argv[0]);
+    return options.print_help() ? 0 : 1;
+  }
+
+  std::ifstream input_file_handle;
+  if (!options.read_from_stdin()) {
+    input_file_handle.open(options.input_filename().c_str());
+    if (!input_file_handle.is_open()) {
+      std::cerr << "ERROR: Could not open '" << options.input_filename()
+                << "' for reading.\n";
+      return 2;
+    }
+  }
+  std::istream& input_stream =
+      options.read_from_stdin() ? std::cin : input_file_handle;
+
+  if (options.rebaseline()) {
+    options.UpdateFromHeader(input_stream);
+    CHECK(options.Validate());
+  }
+
+  std::vector<std::string> snippet_list;
+  ExtractSnippets(&snippet_list, input_stream, options.read_raw_js_snippet());
+
+  std::ofstream output_file_handle;
+  if (!options.write_to_stdout()) {
+    output_file_handle.open(options.rebaseline()
+                                ? options.input_filename().c_str()
+                                : options.output_filename().c_str());
+    if (!output_file_handle.is_open()) {
+      std::cerr << "ERROR: Could not open '" << options.output_filename()
+                << "' for writing.\n";
+      return 3;
+    }
+  }
+  std::ostream& output_stream =
+      options.write_to_stdout() ? std::cout : output_file_handle;
+
+  GenerateExpectationsFile(output_stream, snippet_list, options, argv[0]);
+}
diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc
index 2c06da2..73767eb 100644
--- a/test/cctest/interpreter/test-bytecode-generator.cc
+++ b/test/cctest/interpreter/test-bytecode-generator.cc
@@ -15,6 +15,8 @@
 namespace internal {
 namespace interpreter {
 
+static const InstanceType kInstanceTypeDontCare = static_cast<InstanceType>(-1);
+
 class BytecodeGeneratorHelper {
  public:
   const char* kFunctionName = "f";
@@ -24,12 +26,9 @@
 
   BytecodeGeneratorHelper() {
     i::FLAG_ignition = true;
-    i::FLAG_ignition_fake_try_catch = true;
-    i::FLAG_ignition_fallback_on_eval_and_catch = false;
     i::FLAG_ignition_filter = StrDup(kFunctionName);
     i::FLAG_always_opt = false;
     i::FLAG_allow_natives_syntax = true;
-    i::FLAG_legacy_const = true;
     CcTest::i_isolate()->interpreter()->Initialize();
   }
 
@@ -94,6 +93,7 @@
 #define B(x) static_cast<uint8_t>(Bytecode::k##x)
 #define U8(x) static_cast<uint8_t>((x) & 0xff)
 #define R(x) static_cast<uint8_t>(-(x) & 0xff)
+#define R16(x) U16(-(x))
 #define A(x, n) R(helper.kLastParamIndex - (n) + 1 + (x))
 #define THIS(n) A(0, n)
 #if defined(V8_TARGET_LITTLE_ENDIAN)
@@ -160,6 +160,12 @@
   const uint8_t bytecode[2048];
   int constant_count;
   T constants[C];
+  int handler_count;
+  struct {
+    int start;
+    int end;
+    int handler;
+  } handlers[C];
 };
 
 
@@ -186,7 +192,9 @@
 
 
 static void CheckConstant(InstanceType expected, Object* actual) {
-  CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type());
+  if (expected != kInstanceTypeDontCare) {
+    CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type());
+  }
 }
 
 
@@ -204,6 +212,17 @@
       CheckConstant(expected.constants[i], actual->constant_pool()->get(i));
     }
   }
+  if (expected.handler_count == 0) {
+    CHECK_EQ(CcTest::heap()->empty_fixed_array(), actual->handler_table());
+  } else {
+    HandlerTable* table = HandlerTable::cast(actual->handler_table());
+    CHECK_EQ(expected.handler_count, table->NumberOfRangeEntries());
+    for (int i = 0; i < expected.handler_count; i++) {
+      CHECK_EQ(expected.handlers[i].start, table->GetRangeStart(i));
+      CHECK_EQ(expected.handlers[i].end, table->GetRangeEnd(i));
+      CHECK_EQ(expected.handlers[i].handler, table->GetRangeHandler(i));
+    }
+  }
 
   BytecodeArrayIterator iterator(actual);
   int i = 0;
@@ -258,18 +277,110 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
-      {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0},
-      {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0},
-      {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0},
-      {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0},
-      {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0},
-      {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0},
-      {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0},
-      {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0},
-      {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0},
-      {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0},
+      {"",
+       0,
+       1,
+       3,
+       {
+           B(StackCheck),    //
+           B(LdaUndefined),  //
+           B(Return)         //
+       },
+       0},
+      {"return;",
+       0,
+       1,
+       3,
+       {
+           B(StackCheck),    //
+           B(LdaUndefined),  //
+           B(Return)         //
+       },
+       0},
+      {"return null;",
+       0,
+       1,
+       3,
+       {
+           B(StackCheck),  //
+           B(LdaNull),     //
+           B(Return)       //
+       },
+       0},
+      {"return true;",
+       0,
+       1,
+       3,
+       {
+           B(StackCheck),  //
+           B(LdaTrue),     //
+           B(Return)       //
+       },
+       0},
+      {"return false;",
+       0,
+       1,
+       3,
+       {
+           B(StackCheck),  //
+           B(LdaFalse),    //
+           B(Return)       //
+       },
+       0},
+      {"return 0;",
+       0,
+       1,
+       3,
+       {
+           B(StackCheck),  //
+           B(LdaZero),     //
+           B(Return)       //
+       },
+       0},
+      {"return +1;",
+       0,
+       1,
+       4,
+       {
+           B(StackCheck),      //
+           B(LdaSmi8), U8(1),  //
+           B(Return)           //
+       },
+       0},
+      {"return -1;",
+       0,
+       1,
+       4,
+       {
+           B(StackCheck),       //
+           B(LdaSmi8), U8(-1),  //
+           B(Return)            //
+       },
+       0},
+      {"return +127;",
+       0,
+       1,
+       4,
+       {
+           B(StackCheck),        //
+           B(LdaSmi8), U8(127),  //
+           B(Return)             //
+       },
+       0},
+      {"return -128;",
+       0,
+       1,
+       4,
+       {
+           B(StackCheck),         //
+           B(LdaSmi8), U8(-128),  //
+           B(Return)              //
+       },
+       0},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -283,20 +394,23 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"var x = 0; return x;",
        kPointerSize,
        1,
-       4,
-       {B(LdaZero),     //
+       5,
+       {B(StackCheck),  //
+        B(LdaZero),     //
         B(Star), R(0),  //
         B(Return)},
        0},
       {"var x = 0; return x + 3;",
        2 * kPointerSize,
        1,
-       10,
-       {B(LdaZero),         //
+       11,
+       {B(StackCheck),      //
+        B(LdaZero),         //
         B(Star), R(0),      //
         B(Star), R(1),      //
         B(LdaSmi8), U8(3),  //
@@ -306,8 +420,9 @@
       {"var x = 0; return x - 3;",
        2 * kPointerSize,
        1,
-       10,
-       {B(LdaZero),         //
+       11,
+       {B(StackCheck),      //
+        B(LdaZero),         //
         B(Star), R(0),      //
         B(Star), R(1),      //
         B(LdaSmi8), U8(3),  //
@@ -317,8 +432,9 @@
       {"var x = 4; return x * 3;",
        2 * kPointerSize,
        1,
-       11,
-       {B(LdaSmi8), U8(4),  //
+       12,
+       {B(StackCheck),      //
+        B(LdaSmi8), U8(4),  //
         B(Star), R(0),      //
         B(Star), R(1),      //
         B(LdaSmi8), U8(3),  //
@@ -328,8 +444,9 @@
       {"var x = 4; return x / 3;",
        2 * kPointerSize,
        1,
-       11,
-       {B(LdaSmi8), U8(4),  //
+       12,
+       {B(StackCheck),      //
+        B(LdaSmi8), U8(4),  //
         B(Star), R(0),      //
         B(Star), R(1),      //
         B(LdaSmi8), U8(3),  //
@@ -339,8 +456,9 @@
       {"var x = 4; return x % 3;",
        2 * kPointerSize,
        1,
-       11,
-       {B(LdaSmi8), U8(4),  //
+       12,
+       {B(StackCheck),      //
+        B(LdaSmi8), U8(4),  //
         B(Star), R(0),      //
         B(Star), R(1),      //
         B(LdaSmi8), U8(3),  //
@@ -350,8 +468,9 @@
       {"var x = 1; return x | 2;",
        2 * kPointerSize,
        1,
-       11,
-       {B(LdaSmi8), U8(1),   //
+       12,
+       {B(StackCheck),       //
+        B(LdaSmi8), U8(1),   //
         B(Star), R(0),       //
         B(Star), R(1),       //
         B(LdaSmi8), U8(2),   //
@@ -361,8 +480,9 @@
       {"var x = 1; return x ^ 2;",
        2 * kPointerSize,
        1,
-       11,
-       {B(LdaSmi8), U8(1),    //
+       12,
+       {B(StackCheck),        //
+        B(LdaSmi8), U8(1),    //
         B(Star), R(0),        //
         B(Star), R(1),        //
         B(LdaSmi8), U8(2),    //
@@ -372,8 +492,9 @@
       {"var x = 1; return x & 2;",
        2 * kPointerSize,
        1,
-       11,
-       {B(LdaSmi8), U8(1),    //
+       12,
+       {B(StackCheck),        //
+        B(LdaSmi8), U8(1),    //
         B(Star), R(0),        //
         B(Star), R(1),        //
         B(LdaSmi8), U8(2),    //
@@ -383,8 +504,9 @@
       {"var x = 10; return x << 3;",
        2 * kPointerSize,
        1,
-       11,
-       {B(LdaSmi8), U8(10),  //
+       12,
+       {B(StackCheck),       //
+        B(LdaSmi8), U8(10),  //
         B(Star), R(0),       //
         B(Star), R(1),       //
         B(LdaSmi8), U8(3),   //
@@ -394,8 +516,9 @@
       {"var x = 10; return x >> 3;",
        2 * kPointerSize,
        1,
-       11,
-       {B(LdaSmi8), U8(10),   //
+       12,
+       {B(StackCheck),        //
+        B(LdaSmi8), U8(10),   //
         B(Star), R(0),        //
         B(Star), R(1),        //
         B(LdaSmi8), U8(3),    //
@@ -405,8 +528,9 @@
       {"var x = 10; return x >>> 3;",
        2 * kPointerSize,
        1,
-       11,
-       {B(LdaSmi8), U8(10),          //
+       12,
+       {B(StackCheck),               //
+        B(LdaSmi8), U8(10),          //
         B(Star), R(0),               //
         B(Star), R(1),               //
         B(LdaSmi8), U8(3),           //
@@ -416,12 +540,15 @@
       {"var x = 0; return (x, 3);",
        1 * kPointerSize,
        1,
-       6,
-       {B(LdaZero),         //
+       7,
+       {B(StackCheck),      //
+        B(LdaZero),         //
         B(Star), R(0),      //
         B(LdaSmi8), U8(3),  //
         B(Return)},
-       0}};
+       0},
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -435,12 +562,14 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"var x = 0; return x || 3;",
        1 * kPointerSize,
        1,
-       8,
-       {B(LdaZero),                     //
+       9,
+       {B(StackCheck),                  //
+        B(LdaZero),                     //
         B(Star), R(0),                  //
         B(JumpIfToBooleanTrue), U8(4),  //
         B(LdaSmi8), U8(3),              //
@@ -449,8 +578,9 @@
       {"var x = 0; return (x == 1) || 3;",
        2 * kPointerSize,
        1,
-       14,
-       {B(LdaZero),            //
+       15,
+       {B(StackCheck),         //
+        B(LdaZero),            //
         B(Star), R(0),         //
         B(Star), R(1),         //
         B(LdaSmi8), U8(1),     //
@@ -462,8 +592,9 @@
       {"var x = 0; return x && 3;",
        1 * kPointerSize,
        1,
-       8,
-       {B(LdaZero),                      //
+       9,
+       {B(StackCheck),                   //
+        B(LdaZero),                      //
         B(Star), R(0),                   //
         B(JumpIfToBooleanFalse), U8(4),  //
         B(LdaSmi8), U8(3),               //
@@ -472,8 +603,9 @@
       {"var x = 0; return (x == 0) && 3;",
        2 * kPointerSize,
        1,
-       13,
-       {B(LdaZero),             //
+       14,
+       {B(StackCheck),          //
+        B(LdaZero),             //
         B(Star), R(0),          //
         B(Star), R(1),          //
         B(LdaZero),             //
@@ -485,8 +617,9 @@
       {"var x = 0; return x || (1, 2, 3);",
        1 * kPointerSize,
        1,
-       8,
-       {B(LdaZero),                     //
+       9,
+       {B(StackCheck),                  //
+        B(LdaZero),                     //
         B(Star), R(0),                  //
         B(JumpIfToBooleanTrue), U8(4),  //
         B(LdaSmi8), U8(3),              //
@@ -495,8 +628,9 @@
       {"var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);",
        3 * kPointerSize,
        1,
-       31,
-       {B(LdaSmi8), U8(2),               //
+       32,
+       {B(StackCheck),                   //
+        B(LdaSmi8), U8(2),               //
         B(Star), R(0),                   //
         B(LdaSmi8), U8(3),               //
         B(Star), R(1),                   //
@@ -518,8 +652,9 @@
        "3);",
        3 * kPointerSize,
        1,
-       275,
-       {B(LdaSmi8), U8(1),                      //
+       276,
+       {B(StackCheck),                          //
+        B(LdaSmi8), U8(1),                      //
         B(Star), R(0),                          //
         B(LdaSmi8), U8(2),                      //
         B(Star), R(1),                          //
@@ -541,8 +676,9 @@
        "3);",
        3 * kPointerSize,
        1,
-       274,
-       {B(LdaZero),                              //
+       275,
+       {B(StackCheck),                           //
+        B(LdaZero),                              //
         B(Star), R(0),                           //
         B(LdaSmi8), U8(2),                       //
         B(Star), R(1),                           //
@@ -564,8 +700,9 @@
        "3);",
        4 * kPointerSize,
        1,
-       281,
-       {B(LdaSmi8), U8(1),             //
+       282,
+       {B(StackCheck),                 //
+        B(LdaSmi8), U8(1),             //
         B(Star), R(0),                 //
         B(LdaSmi8), U8(2),             //
         B(Star), R(1),                 //
@@ -590,8 +727,9 @@
        "3);",
        4 * kPointerSize,
        1,
-       280,
-       {B(LdaZero),                     //
+       281,
+       {B(StackCheck),                  //
+        B(LdaZero),                     //
         B(Star), R(0),                  //
         B(LdaSmi8), U8(2),              //
         B(Star), R(1),                  //
@@ -614,22 +752,25 @@
       {"return 0 && 3;",
        0 * kPointerSize,
        1,
-       2,
-       {B(LdaZero),  //
+       3,
+       {B(StackCheck),  //
+        B(LdaZero),     //
         B(Return)},
        0},
       {"return 1 || 3;",
        0 * kPointerSize,
        1,
-       3,
-       {B(LdaSmi8), U8(1),  //
+       4,
+       {B(StackCheck),      //
+        B(LdaSmi8), U8(1),  //
         B(Return)},
        0},
       {"var x = 1; return x && 3 || 0, 1;",
        1 * kPointerSize,
        1,
-       14,
-       {B(LdaSmi8), U8(1),               //
+       15,
+       {B(StackCheck),                   //
+        B(LdaSmi8), U8(1),               //
         B(Star), R(0),                   //
         B(JumpIfToBooleanFalse), U8(4),  //
         B(LdaSmi8), U8(3),               //
@@ -637,7 +778,9 @@
         B(LdaZero),                      //
         B(LdaSmi8), U8(1),               //
         B(Return)},
-       0}};
+       0}
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -651,42 +794,54 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"function f() { return this; }",
        0,
        1,
-       3,
-       {B(Ldar), THIS(1), B(Return)},
+       4,
+       {B(StackCheck),     //
+        B(Ldar), THIS(1),  //
+        B(Return)},
        0},
       {"function f(arg1) { return arg1; }",
        0,
        2,
-       3,
-       {B(Ldar), A(1, 2), B(Return)},
+       4,
+       {B(StackCheck),     //
+        B(Ldar), A(1, 2),  //
+        B(Return)},
        0},
       {"function f(arg1) { return this; }",
        0,
        2,
-       3,
-       {B(Ldar), THIS(2), B(Return)},
+       4,
+       {B(StackCheck),     //
+        B(Ldar), THIS(2),  //
+        B(Return)},
        0},
       {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }",
        0,
        8,
-       3,
-       {B(Ldar), A(4, 8), B(Return)},
+       4,
+       {B(StackCheck),     //
+        B(Ldar), A(4, 8),  //
+        B(Return)},
        0},
       {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }",
        0,
        8,
-       3,
-       {B(Ldar), THIS(8), B(Return)},
+       4,
+       {B(StackCheck),     //
+        B(Ldar), THIS(8),  //
+        B(Return)},
        0},
       {"function f(arg1) { arg1 = 1; }",
        0,
        2,
-       6,
-       {B(LdaSmi8), U8(1),  //
+       7,
+       {B(StackCheck),      //
+        B(LdaSmi8), U8(1),  //
         B(Star), A(1, 2),   //
         B(LdaUndefined),    //
         B(Return)},
@@ -694,13 +849,15 @@
       {"function f(arg1, arg2, arg3, arg4) { arg2 = 1; }",
        0,
        5,
-       6,
-       {B(LdaSmi8), U8(1),  //
+       7,
+       {B(StackCheck),      //
+        B(LdaSmi8), U8(1),  //
         B(Star), A(2, 5),   //
         B(LdaUndefined),    //
         B(Return)},
        0},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -714,12 +871,14 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
     {"return 12345678;",
      0,
      1,
-     3,
+     4,
      {
+       B(StackCheck),          //
        B(LdaConstant), U8(0),  //
        B(Return)               //
      },
@@ -728,8 +887,9 @@
     {"var a = 1234; return 5678;",
      1 * kPointerSize,
      1,
-     7,
+     8,
      {
+       B(StackCheck),          //
        B(LdaConstant), U8(0),  //
        B(Star), R(0),          //
        B(LdaConstant), U8(1),  //
@@ -740,15 +900,18 @@
     {"var a = 1234; return 1234;",
      1 * kPointerSize,
      1,
-     7,
+     8,
      {
+       B(StackCheck),          //
        B(LdaConstant), U8(0),  //
        B(Star), R(0),          //
        B(LdaConstant), U8(0),  //
        B(Return)               //
      },
      1,
-     {1234}}};
+     {1234}}
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -764,12 +927,14 @@
 
   int wide_idx = 0;
 
+  // clang-format off
   ExpectedSnippet<double, 257> snippets[] = {
     {"return 1.2;",
      0,
      1,
-     3,
+     4,
      {
+       B(StackCheck),          //
        B(LdaConstant), U8(0),  //
        B(Return)               //
      },
@@ -778,8 +943,9 @@
     {"var a = 1.2; return 2.6;",
      1 * kPointerSize,
      1,
-     7,
+     8,
      {
+       B(StackCheck),          //
        B(LdaConstant), U8(0),  //
        B(Star), R(0),          //
        B(LdaConstant), U8(1),  //
@@ -790,8 +956,9 @@
     {"var a = 3.14; return 3.14;",
      1 * kPointerSize,
      1,
-     7,
+     8,
      {
+       B(StackCheck),          //
        B(LdaConstant), U8(0),  //
        B(Star), R(0),          //
        B(LdaConstant), U8(1),  //
@@ -804,8 +971,9 @@
      " a = 3.14;",
      1 * kPointerSize,
      1,
-     1031,
+     1032,
      {
+         B(StackCheck),                        //
          REPEAT_256(COMMA,                     //
            B(LdaConstant), U8(wide_idx++),     //
            B(Star), R(0)),                     //
@@ -818,6 +986,8 @@
      {REPEAT_256(COMMA, 1.414),
       3.14}}
   };
+  // clang-format on
+
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
         helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
@@ -830,12 +1000,14 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"return \"This is a string\";",
        0,
        1,
-       3,
+       4,
        {
+           B(StackCheck),          //
            B(LdaConstant), U8(0),  //
            B(Return)               //
        },
@@ -844,8 +1016,9 @@
       {"var a = \"First string\"; return \"Second string\";",
        1 * kPointerSize,
        1,
-       7,
+       8,
        {
+           B(StackCheck),          //
            B(LdaConstant), U8(0),  //
            B(Star), R(0),          //
            B(LdaConstant), U8(1),  //
@@ -856,15 +1029,18 @@
       {"var a = \"Same string\"; return \"Same string\";",
        1 * kPointerSize,
        1,
-       7,
+       8,
        {
+           B(StackCheck),          //
            B(LdaConstant), U8(0),  //
            B(Star), R(0),          //
            B(LdaConstant), U8(0),  //
            B(Return)               //
        },
        1,
-       {"Same string"}}};
+       {"Same string"}}
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -889,18 +1065,18 @@
   // These are a hack used by the LoadICXXXWide tests below.
   int wide_idx_1 = vector->GetIndex(slot1) - 2;
   int wide_idx_2 = vector->GetIndex(slot1) - 2;
-  int wide_idx_3 = vector->GetIndex(slot1) - 2;
-  int wide_idx_4 = vector->GetIndex(slot1) - 2;
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"function f(a) { return a.name; }\nf({name : \"test\"})",
        1 * kPointerSize,
        2,
-       9,
+       10,
        {
+           B(StackCheck),                                              //
            B(Ldar), A(1, 2),                                           //
            B(Star), R(0),                                              //
-           B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(LoadIC), R(0), U8(0), U8(vector->GetIndex(slot1)),  //
            B(Return),                                                  //
        },
        1,
@@ -908,11 +1084,12 @@
       {"function f(a) { return a[\"key\"]; }\nf({key : \"test\"})",
        1 * kPointerSize,
        2,
-       9,
+       10,
        {
+           B(StackCheck),                                              //
            B(Ldar), A(1, 2),                                           //
            B(Star), R(0),                                              //
-           B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(LoadIC), R(0), U8(0), U8(vector->GetIndex(slot1)),  //
            B(Return)                                                   //
        },
        1,
@@ -920,24 +1097,26 @@
       {"function f(a) { return a[100]; }\nf({100 : \"test\"})",
        1 * kPointerSize,
        2,
-       10,
+       11,
        {
+           B(StackCheck),                                            //
            B(Ldar), A(1, 2),                                         //
            B(Star), R(0),                                            //
            B(LdaSmi8), U8(100),                                      //
-           B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)),  //
+           B(KeyedLoadIC), R(0), U8(vector->GetIndex(slot1)),  //
            B(Return)                                                 //
        },
        0},
       {"function f(a, b) { return a[b]; }\nf({arg : \"test\"}, \"arg\")",
        1 * kPointerSize,
        3,
-       10,
+       11,
        {
+           B(StackCheck),                                            //
            B(Ldar), A(1, 3),                                         //
            B(Star), R(0),                                            //
            B(Ldar), A(1, 2),                                         //
-           B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)),  //
+           B(KeyedLoadIC), R(0), U8(vector->GetIndex(slot1)),  //
            B(Return)                                                 //
        },
        0},
@@ -945,45 +1124,21 @@
        "f({\"-124\" : \"test\", name : 123 })",
        2 * kPointerSize,
        2,
-       20,
+       21,
        {
+           B(StackCheck),                                              //
            B(Ldar), A(1, 2),                                           //
            B(Star), R(1),                                              //
-           B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot1)),  //
            B(Star), R(0),                                              //
            B(Ldar), A(1, 2),                                           //
            B(Star), R(1),                                              //
            B(LdaSmi8), U8(-124),                                       //
-           B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot2)),    //
+           B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot2)),    //
            B(Return),                                                  //
        },
        1,
        {"name"}},
-      {"function f(a) { \"use strict\"; return a.name; }\nf({name : \"test\"})",
-       1 * kPointerSize,
-       2,
-       9,
-       {
-           B(Ldar), A(1, 2),                                           //
-           B(Star), R(0),                                              //
-           B(LoadICStrict), R(0), U8(0), U8(vector->GetIndex(slot1)),  //
-           B(Return),                                                  //
-       },
-       1,
-       {"name"}},
-      {"function f(a, b) { \"use strict\"; return a[b]; }\n"
-       "f({arg : \"test\"}, \"arg\")",
-       1 * kPointerSize,
-       3,
-       10,
-       {
-           B(Ldar), A(1, 3),                                         //
-           B(Star), R(0),                                            //
-           B(Ldar), A(2, 3),                                         //
-           B(KeyedLoadICStrict), R(0), U8(vector->GetIndex(slot1)),  //
-           B(Return),                                                //
-       },
-       0},
       {"function f(a) {\n"
        " var b;\n"
        "b = a.name;"
@@ -992,48 +1147,22 @@
        "f({name : \"test\"})\n",
        2 * kPointerSize,
        2,
-       1291,
+       1292,
        {
+           B(StackCheck),                                           //
            B(Ldar), A(1, 2),                                        //
            B(Star), R(1),                                           //
-           B(LoadICSloppy), R(1), U8(0), U8(wide_idx_1 += 2),       //
+           B(LoadIC), R(1), U8(0), U8(wide_idx_1 += 2),       //
            B(Star), R(0),                                           //
            REPEAT_127(COMMA,                                        //
                       B(Ldar), A(1, 2),                             //
                       B(Star), R(1),                                //
-                      B(LoadICSloppy), R(1), U8(0),                 //
+                      B(LoadIC), R(1), U8(0),                 //
                                        U8((wide_idx_1 += 2)),       //
                       B(Star), R(0)),                               //
            B(Ldar), A(1, 2),                                        //
            B(Star), R(1),                                           //
-           B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx_1 + 2),  //
-           B(Return),                                               //
-       },
-       1,
-       {"name"}},
-      {"function f(a) {\n"
-       " 'use strict'; var b;\n"
-       "  b = a.name;\n"
-       REPEAT_127(SPACE, " b = a.name; ")
-       " return a.name; }\n"
-       "f({name : \"test\"})\n",
-       2 * kPointerSize,
-       2,
-       1291,
-       {
-           B(Ldar), A(1, 2),                                        //
-           B(Star), R(1),                                           //
-           B(LoadICStrict), R(1), U8(0), U8((wide_idx_2 += 2)),     //
-           B(Star), R(0),                                           //
-           REPEAT_127(COMMA,                                        //
-                      B(Ldar), A(1, 2),                             //
-                      B(Star), R(1),                                //
-                      B(LoadICStrict), R(1), U8(0),                 //
-                                       U8((wide_idx_2 += 2)),       //
-                      B(Star), R(0)),                               //
-           B(Ldar), A(1, 2),                                        //
-           B(Star), R(1),                                           //
-           B(LoadICStrictWide), R(1), U16(0), U16(wide_idx_2 + 2),  //
+           B(LoadICWide), R(1), U16(0), U16(wide_idx_1 + 2),  //
            B(Return),                                               //
        },
        1,
@@ -1046,53 +1175,29 @@
        "f({name : \"test\"}, \"name\")\n",
        2 * kPointerSize,
        3,
-       1419,
+       1420,
        {
+           B(StackCheck),                                                 //
            B(Ldar), A(1, 3),                                              //
            B(Star), R(1),                                                 //
            B(Ldar), A(2, 3),                                              //
-           B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)),             //
+           B(KeyedLoadIC), R(1), U8((wide_idx_2 += 2)),             //
            B(Star), R(0),                                                 //
            REPEAT_127(COMMA,                                              //
                       B(Ldar), A(1, 3),                                   //
                       B(Star), R(1),                                      //
                       B(Ldar), A(2, 3),                                   //
-                      B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)),  //
+                      B(KeyedLoadIC), R(1), U8((wide_idx_2 += 2)),  //
                       B(Star), R(0)),                                     //
            B(Ldar), A(1, 3),                                              //
            B(Star), R(1),                                                 //
            B(Ldar), A(2, 3),                                              //
-           B(KeyedLoadICSloppyWide), R(1), U16(wide_idx_3 + 2),           //
-           B(Return),                                                     //
-       }},
-      {"function f(a, b) {\n"
-       " 'use strict'; var c;\n"
-       "  c = a[b];"
-       REPEAT_127(SPACE, " c = a[b]; ")
-       " return a[b]; }\n"
-       "f({name : \"test\"}, \"name\")\n",
-       2 * kPointerSize,
-       3,
-       1419,
-       {
-           B(Ldar), A(1, 3),                                              //
-           B(Star), R(1),                                                 //
-           B(Ldar), A(2, 3),                                              //
-           B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)),             //
-           B(Star), R(0),                                                 //
-           REPEAT_127(COMMA,                                              //
-                      B(Ldar), A(1, 3),                                   //
-                      B(Star), R(1),                                      //
-                      B(Ldar), A(2, 3),                                   //
-                      B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)),  //
-                      B(Star), R(0)),                                     //
-           B(Ldar), A(1, 3),                                              //
-           B(Star), R(1),                                                 //
-           B(Ldar), A(2, 3),                                              //
-           B(KeyedLoadICStrictWide), R(1), U16(wide_idx_4 + 2),           //
+           B(KeyedLoadICWide), R(1), U16(wide_idx_2 + 2),           //
            B(Return),                                                     //
        }},
   };
+  // clang-format on
+
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
         helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
@@ -1119,12 +1224,14 @@
   int wide_idx_3 = vector->GetIndex(slot1) - 2;
   int wide_idx_4 = vector->GetIndex(slot1) - 2;
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})",
        kPointerSize,
        2,
-       12,
+       13,
        {
+           B(StackCheck),                                               //
            B(Ldar), A(1, 2),                                            //
            B(Star), R(0),                                               //
            B(LdaConstant), U8(0),                                       //
@@ -1137,8 +1244,9 @@
       {"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})",
        kPointerSize,
        2,
-       12,
+       13,
        {
+           B(StackCheck),                                               //
            B(Ldar), A(1, 2),                                            //
            B(Star), R(0),                                               //
            B(LdaConstant), U8(0),                                       //
@@ -1151,8 +1259,9 @@
       {"function f(a) { a[100] = \"val\"; }\nf({100 : \"test\"})",
        2 * kPointerSize,
        2,
-       16,
+       17,
        {
+           B(StackCheck),                      //
            B(Ldar), A(1, 2),                   //
            B(Star), R(0),                      //
            B(LdaSmi8), U8(100),                //
@@ -1168,8 +1277,9 @@
       {"function f(a, b) { a[b] = \"val\"; }\nf({arg : \"test\"}, \"arg\")",
        2 * kPointerSize,
        3,
-       16,
+       17,
        {
+           B(StackCheck),                      //
            B(Ldar), A(1, 3),                   //
            B(Star), R(0),                      //
            B(Ldar), A(2, 3),                   //
@@ -1186,14 +1296,15 @@
        "f({\"-124\" : \"test\", name : 123 })",
        2 * kPointerSize,
        2,
-       19,
+       20,
        {
+           B(StackCheck),                                               //
            B(Ldar), A(1, 2),                                            //
            B(Star), R(0),                                               //
            B(Ldar), A(1, 2),                                            //
            B(Star), R(1),                                               //
            B(LdaSmi8), U8(-124),                                        //
-           B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)),     //
+           B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot1)),     //
            B(StoreICSloppy), R(0), U8(0), U8(vector->GetIndex(slot2)),  //
            B(LdaUndefined),                                             //
            B(Return),                                                   //
@@ -1204,8 +1315,9 @@
        "f({name : \"test\"})",
        kPointerSize,
        2,
-       12,
+       13,
        {
+           B(StackCheck),                                               //
            B(Ldar), A(1, 2),                                            //
            B(Star), R(0),                                               //
            B(LdaConstant), U8(0),                                       //
@@ -1219,8 +1331,9 @@
        "f({arg : \"test\"}, \"arg\")",
        2 * kPointerSize,
        3,
-       16,
+       17,
        {
+           B(StackCheck),                                                   //
            B(Ldar), A(1, 3),                                                //
            B(Star), R(0),                                                   //
            B(Ldar), A(2, 3),                                                //
@@ -1239,8 +1352,9 @@
        "f({name : \"test\"})\n",
        kPointerSize,
        2,
-       1294,
+       1295,
        {
+           B(StackCheck),                                            //
            B(Ldar), A(1, 2),                                         //
            B(Star), R(0),                                            //
            B(LdaSmi8), U8(1),                                        //
@@ -1268,8 +1382,9 @@
        "f({name : \"test\"})\n",
        kPointerSize,
        2,
-       1294,
+       1295,
        {
+           B(StackCheck),                                            //
            B(Ldar), A(1, 2),                                         //
            B(Star), R(0),                                            //
            B(LdaSmi8), U8(1),                                        //
@@ -1296,8 +1411,9 @@
        "f({name : \"test\"})\n",
        2 * kPointerSize,
        3,
-       1809,
+       1810,
        {
+           B(StackCheck),                                               //
            B(Ldar), A(1, 3),                                            //
            B(Star), R(0),                                               //
            B(Ldar), A(2, 3),                                            //
@@ -1329,8 +1445,9 @@
        "f({name : \"test\"})\n",
        2 * kPointerSize,
        3,
-       1809,
+       1810,
        {
+           B(StackCheck),                                               //
            B(Ldar), A(1, 3),                                            //
            B(Star), R(0),                                               //
            B(Ldar), A(2, 3),                                            //
@@ -1353,7 +1470,10 @@
            B(KeyedStoreICStrictWide), R(0), R(1), U16(wide_idx_4 + 2),  //
            B(LdaUndefined),                                             //
            B(Return),                                                   //
-       }}};
+       }}
+  };
+  // clang-format on
+
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
         helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
@@ -1380,17 +1500,19 @@
   // These are a hack used by the CallWide test below.
   int wide_idx = vector->GetIndex(slot1) - 2;
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"function f(a) { return a.func(); }\nf(" FUNC_ARG ")",
        2 * kPointerSize,
        2,
-       16,
+       17,
        {
+           B(StackCheck),                                              //
            B(Ldar), A(1, 2),                                           //
            B(Star), R(1),                                              //
-           B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)),  //
+           B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)),  //
            B(Star), R(0),                                              //
-           B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)),    //
+           B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)),    //
            B(Return),                                                  //
        },
        1,
@@ -1398,17 +1520,18 @@
       {"function f(a, b, c) { return a.func(b, c); }\nf(" FUNC_ARG ", 1, 2)",
        4 * kPointerSize,
        4,
-       24,
+       25,
        {
+           B(StackCheck),                                              //
            B(Ldar), A(1, 4),                                           //
            B(Star), R(1),                                              //
-           B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)),  //
+           B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)),  //
            B(Star), R(0),                                              //
            B(Ldar), A(2, 4),                                           //
            B(Star), R(2),                                              //
            B(Ldar), A(3, 4),                                           //
            B(Star), R(3),                                              //
-           B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)),    //
+           B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)),    //
            B(Return)                                                   //
        },
        1,
@@ -1416,11 +1539,12 @@
       {"function f(a, b) { return a.func(b + b, b); }\nf(" FUNC_ARG ", 1)",
        4 * kPointerSize,
        3,
-       30,
+       31,
        {
+           B(StackCheck),                                              //
            B(Ldar), A(1, 3),                                           //
            B(Star), R(1),                                              //
-           B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)),  //
+           B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)),  //
            B(Star), R(0),                                              //
            B(Ldar), A(2, 3),                                           //
            B(Star), R(3),                                              //
@@ -1429,36 +1553,38 @@
            B(Star), R(2),                                              //
            B(Ldar), A(2, 3),                                           //
            B(Star), R(3),                                              //
-           B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)),    //
+           B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)),    //
            B(Return),                                                  //
        },
        1,
        {"func"}},
       {"function f(a) {\n"
-       " a.func;\n"
-       REPEAT_127(SPACE, " a.func;\n")
-       " return a.func(); }\nf(" FUNC_ARG ")",
+       " a.func;\n" REPEAT_127(
+           SPACE, " a.func;\n") " return a.func(); }\nf(" FUNC_ARG ")",
        2 * kPointerSize,
        2,
-       1044,
+       1047,
        {
+           B(StackCheck),                                                  //
            B(Ldar), A(1, 2),                                               //
            B(Star), R(0),                                                  //
-           B(LoadICSloppy), R(0), U8(0), U8(wide_idx += 2),                //
+           B(LoadIC), R(0), U8(0), U8(wide_idx += 2),                //
            REPEAT_127(COMMA,                                               //
                       B(Ldar), A(1, 2),                                    //
                       B(Star), R(0),                                       //
-                      B(LoadICSloppy), R(0), U8(0), U8((wide_idx += 2))),  //
+                      B(LoadIC), R(0), U8(0), U8((wide_idx += 2))),  //
            B(Ldar), A(1, 2),                                               //
            B(Star), R(1),                                                  //
-           B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx + 4),           //
+           B(LoadICWide), R(1), U16(0), U16(wide_idx + 4),           //
            B(Star), R(0),                                                  //
-           B(CallWide), R(0), R(1), U16(0), U16(wide_idx + 2),             //
+           B(CallWide), R16(0), R16(1), U16(1), U16(wide_idx + 2),         //
            B(Return),                                                      //
        },
        1,
        {"func"}},
   };
+  // clang-format on
+
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
         helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
@@ -1480,15 +1606,16 @@
 
   // These are a hack used by the LdaGlobalXXXWide tests below.
   int wide_idx_1 = vector->GetIndex(slot) - 2;
-  int wide_idx_2 = vector->GetIndex(slot) - 2;
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"var a = 1;\nfunction f() { return a; }\nf()",
        0,
        1,
-       4,
+       5,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)),  //
+           B(StackCheck),                                          //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)),  //
            B(Return)                                               //
        },
        1,
@@ -1496,29 +1623,21 @@
       {"function t() { }\nfunction f() { return t; }\nf()",
        0,
        1,
-       4,
+       5,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)),  //
+           B(StackCheck),                                          //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)),  //
            B(Return)                                               //
        },
        1,
        {"t"}},
-      {"'use strict'; var a = 1;\nfunction f() { return a; }\nf()",
-       0,
-       1,
-       4,
-       {
-           B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)),  //
-           B(Return)                                               //
-       },
-       1,
-       {"a"}},
       {"a = 1;\nfunction f() { return a; }\nf()",
        0,
        1,
-       4,
+       5,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)),  //
+           B(StackCheck),                                          //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)),  //
            B(Return)                                               //
        },
        1,
@@ -1531,44 +1650,23 @@
        "}\nf({name: 1});",
        kPointerSize,
        2,
-       1030,
+       1031,
        {
+           B(StackCheck),                                                  //
            B(Ldar), A(1, 2),                                               //
            B(Star), R(0),                                                  //
-           B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2),              //
+           B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2),              //
            REPEAT_127(COMMA,                                               //
                       B(Ldar), A(1, 2),                                    //
                       B(Star), R(0),                                       //
-                      B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)),  //
-           B(LdaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2),            //
-           B(Return),                                                      //
-       },
-       2,
-       {"name", "a"}},
-      {"a = 1;"
-       "function f(b) {\n"
-       " 'use strict';\n"
-       "  b.name\n"
-          REPEAT_127(SPACE, "b.name; ")
-       "  return a;"
-       "}\nf({name: 1});",
-       kPointerSize,
-       2,
-       1030,
-       {
-           B(Ldar), A(1, 2),                                               //
-           B(Star), R(0),                                                  //
-           B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2),              //
-           REPEAT_127(COMMA,                                               //
-                      B(Ldar), A(1, 2),                                    //
-                      B(Star), R(0),                                       //
-                      B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)),  //
-           B(LdaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2),            //
+                      B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2)),  //
+           B(LdaGlobalWide), U16(1), U16(wide_idx_1 + 2),            //
            B(Return),                                                      //
        },
        2,
        {"name", "a"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -1593,12 +1691,14 @@
   int wide_idx_1 = vector->GetIndex(slot) - 2;
   int wide_idx_2 = vector->GetIndex(slot) - 2;
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"var a = 1;\nfunction f() { a = 2; }\nf()",
        0,
        1,
-       7,
+       8,
        {
+           B(StackCheck),                                           //
            B(LdaSmi8), U8(2),                                      //
            B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)),  //
            B(LdaUndefined),                                        //
@@ -1609,8 +1709,9 @@
       {"var a = \"test\"; function f(b) { a = b; }\nf(\"global\")",
        0,
        2,
-       7,
+       8,
        {
+           B(StackCheck),                                          //
            B(Ldar), R(helper.kLastParamIndex),                     //
            B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)),  //
            B(LdaUndefined),                                        //
@@ -1621,8 +1722,9 @@
       {"'use strict'; var a = 1;\nfunction f() { a = 2; }\nf()",
        0,
        1,
-       7,
+       8,
        {
+           B(StackCheck),                                          //
            B(LdaSmi8), U8(2),                                      //
            B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot)),  //
            B(LdaUndefined),                                        //
@@ -1633,8 +1735,9 @@
       {"a = 1;\nfunction f() { a = 2; }\nf()",
        0,
        1,
-       7,
+       8,
        {
+           B(StackCheck),                                          //
            B(LdaSmi8), U8(2),                                      //
            B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)),  //
            B(LdaUndefined),                                        //
@@ -1650,15 +1753,16 @@
        "f({name: 1});",
        kPointerSize,
        2,
-       1033,
+       1034,
        {
+           B(StackCheck),                                                  //
            B(Ldar), A(1, 2),                                               //
            B(Star), R(0),                                                  //
-           B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2),              //
+           B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2),              //
            REPEAT_127(COMMA,                                               //
                       B(Ldar), A(1, 2),                                    //
                       B(Star), R(0),                                       //
-                      B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)),  //
+                      B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2)),  //
            B(LdaSmi8), U8(2),                                              //
            B(StaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2),            //
            B(LdaUndefined),                                                //
@@ -1675,15 +1779,16 @@
        "f({name: 1});",
        kPointerSize,
        2,
-       1033,
+       1034,
        {
+           B(StackCheck),                                                  //
            B(Ldar), A(1, 2),                                               //
            B(Star), R(0),                                                  //
-           B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2),              //
+           B(LoadIC), R(0), U8(0), U8(wide_idx_2 += 2),              //
            REPEAT_127(COMMA,                                               //
                       B(Ldar), A(1, 2),                                    //
                       B(Star), R(0),                                       //
-                      B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)),  //
+                      B(LoadIC), R(0), U8(0), U8(wide_idx_2 += 2)),  //
            B(LdaSmi8), U8(2),                                              //
            B(StaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2),            //
            B(LdaUndefined),                                                //
@@ -1692,6 +1797,7 @@
        2,
        {"name", "a"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -1713,17 +1819,19 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"function t() { }\nfunction f() { return t(); }\nf()",
        2 * kPointerSize,
        1,
-       14,
+       15,
        {
+           B(StackCheck),                                            //
            B(LdaUndefined),                                          //
            B(Star), R(1),                                            //
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)),   //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)),   //
            B(Star), R(0),                                            //
-           B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)),  //
            B(Return)                                                 //
        },
        1,
@@ -1731,11 +1839,12 @@
       {"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()",
        5 * kPointerSize,
        1,
-       26,
+       27,
        {
+           B(StackCheck),                                            //
            B(LdaUndefined),                                          //
            B(Star), R(1),                                            //
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)),   //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)),   //
            B(Star), R(0),                                            //
            B(LdaSmi8), U8(1),                                        //
            B(Star), R(2),                                            //
@@ -1743,12 +1852,13 @@
            B(Star), R(3),                                            //
            B(LdaSmi8), U8(3),                                        //
            B(Star), R(4),                                            //
-           B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)),  //
+           B(Call), R(0), R(1), U8(4), U8(vector->GetIndex(slot1)),  //
            B(Return)                                                 //
        },
        1,
        {"t"}},
   };
+  // clang-format on
 
   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   for (size_t i = 0; i < num_snippets; i++) {
@@ -1763,13 +1873,15 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {
           "function f() { %TheHole() }\nf()",
           0,
           1,
-          7,
+          8,
           {
+              B(StackCheck),                                        //
               B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0),  //
               B(LdaUndefined),                                      //
               B(Return)                                             //
@@ -1779,8 +1891,9 @@
           "function f(a) { return %IsArray(a) }\nf(undefined)",
           1 * kPointerSize,
           2,
-          10,
+          11,
           {
+              B(StackCheck),                                        //
               B(Ldar), A(1, 2),                                     //
               B(Star), R(0),                                        //
               B(CallRuntime), U16(Runtime::kIsArray), R(0), U8(1),  //
@@ -1791,8 +1904,9 @@
           "function f() { return %Add(1, 2) }\nf()",
           2 * kPointerSize,
           1,
-          14,
+          15,
           {
+              B(StackCheck),                                    //
               B(LdaSmi8), U8(1),                                //
               B(Star), R(0),                                    //
               B(LdaSmi8), U8(2),                                //
@@ -1805,20 +1919,22 @@
           "function f() { return %spread_iterable([1]) }\nf()",
           2 * kPointerSize,
           1,
-          15,
+          16,
           {
+              B(StackCheck),                                                //
               B(LdaUndefined),                                              //
               B(Star), R(0),                                                //
               B(CreateArrayLiteral), U8(0), U8(0), U8(3),                   //
               B(Star), R(1),                                                //
               B(CallJSRuntime), U16(Context::SPREAD_ITERABLE_INDEX), R(0),  //
-              U8(1),                                                        //
+              /*             */ U8(2),                                      //
               B(Return),                                                    //
           },
           1,
           {InstanceType::FIXED_ARRAY_TYPE},
       },
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -1834,12 +1950,14 @@
 
   Handle<Object> unused = helper.factory()->undefined_value();
 
+  // clang-format off
   ExpectedSnippet<Handle<Object>> snippets[] = {
       {"function f() { if (0) { return 1; } else { return -1; } } f()",
        0,
        1,
-       3,
+       4,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(-1),  //
            B(Return),           //
        },
@@ -1848,8 +1966,9 @@
       {"function f() { if ('lucky') { return 1; } else { return -1; } } f();",
        0,
        1,
-       3,
+       4,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Return),          //
        },
@@ -1858,8 +1977,9 @@
       {"function f() { if (false) { return 1; } else { return -1; } } f();",
        0,
        1,
-       3,
+       4,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(-1),  //
            B(Return),           //
        },
@@ -1868,8 +1988,9 @@
       {"function f() { if (false) { return 1; } } f();",
        0,
        1,
-       2,
+       3,
        {
+           B(StackCheck),    //
            B(LdaUndefined),  //
            B(Return),        //
        },
@@ -1878,8 +1999,9 @@
       {"function f() { var a = 1; if (a) { a += 1; } else { return 2; } } f();",
        2 * kPointerSize,
        1,
-       23,
+       24,
        {
+           B(StackCheck),                    //
            B(LdaSmi8), U8(1),                //
            B(Star), R(0),                    //
            B(JumpIfToBooleanFalse), U8(14),  //
@@ -1900,8 +2022,9 @@
        "f(99);",
        kPointerSize,
        2,
-       17,
+       18,
        {
+           B(StackCheck),                 //
            B(Ldar), A(1, 2),              //
            B(Star), R(0),                 //
            B(LdaZero),                    //
@@ -1922,8 +2045,9 @@
        "f('prop', { prop: 'yes'});",
        kPointerSize,
        3,
-       15,
+       16,
        {
+           B(StackCheck),          //
            B(Ldar), A(1, 3),       //
            B(Star), R(0),          //
            B(Ldar), A(2, 3),       //
@@ -1942,8 +2066,9 @@
        " return 200; } else { return -200; } } f(0.001)",
        3 * kPointerSize,
        2,
-       282,
+       283,
        {
+           B(StackCheck),                  //
            B(LdaZero),                     //
            B(Star), R(0),                  //
            B(LdaZero),                     //
@@ -1973,8 +2098,9 @@
        " return 200; } else { return -200; } } f()",
        2 * kPointerSize,
        1,
-       276,
+       277,
        {
+           B(StackCheck),                           //
            B(LdaZero),                              //
            B(Star), R(0),                           //
            B(LdaZero),                              //
@@ -2009,7 +2135,7 @@
        "} f(1, 1);",
        kPointerSize,
        3,
-       106,
+       107,
        {
 #define IF_CONDITION_RETURN(condition) \
          B(Ldar), A(1, 3),             \
@@ -2019,6 +2145,7 @@
          B(JumpIfFalse), U8(5),        \
          B(LdaSmi8), U8(1),            \
          B(Return),
+           B(StackCheck),                               //
            IF_CONDITION_RETURN(TestEqual)               //
            IF_CONDITION_RETURN(TestEqualStrict)         //
            IF_CONDITION_RETURN(TestLessThan)            //
@@ -2042,8 +2169,9 @@
        "f();",
        1 * kPointerSize,
        1,
-       13,
+       14,
        {
+           B(StackCheck),                   //
            B(LdaZero),                      //
            B(Star), R(0),                   //
            B(JumpIfToBooleanFalse), U8(5),  //
@@ -2055,7 +2183,9 @@
            B(Return)
        },
        0,
-       {unused, unused, unused, unused, unused, unused}}};
+       {unused, unused, unused, unused, unused, unused}}
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -2086,17 +2216,19 @@
   Handle<i::TypeFeedbackVector> load_vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_loads);
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"var a = 1;",
        4 * kPointerSize,
        1,
-       30,
+       31,
        {
            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),                                                       //
@@ -2113,13 +2245,14 @@
       {"function f() {}",
        2 * kPointerSize,
        1,
-       14,
+       15,
        {
            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)                                                    //
        },
@@ -2128,13 +2261,14 @@
       {"var a = 1;\na=2;",
        4 * kPointerSize,
        1,
-       36,
+       37,
        {
            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),                                                       //
@@ -2144,7 +2278,7 @@
            B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3),  //
            B(LdaSmi8), U8(2),                                                //
            B(StaGlobalSloppy), U8(1),                                        //
-                               U8(store_vector->GetIndex(store_slot_2)),     //
+           /*               */ U8(store_vector->GetIndex(store_slot_2)),     //
            B(Star), R(0),                                                    //
            B(Return)                                                         //
        },
@@ -2154,20 +2288,20 @@
       {"function f() {}\nf();",
        3 * kPointerSize,
        1,
-       28,
+       29,
        {
            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(LdaGlobalSloppy), U8(1),                                    //
-                               U8(load_vector->GetIndex(load_slot_1)),   //
+           B(LdaGlobal), U8(1), U8(load_vector->GetIndex(load_slot_1)),  //
            B(Star), R(1),                                                //
-           B(Call), R(1), R(2), U8(0),                                   //
-                                U8(load_vector->GetIndex(call_slot_1)),  //
+           B(Call), R(1), R(2), U8(1),                                   //
+           /*                */ U8(load_vector->GetIndex(call_slot_1)),  //
            B(Star), R(0),                                                //
            B(Return)                                                     //
        },
@@ -2175,6 +2309,7 @@
        {InstanceType::FIXED_ARRAY_TYPE,
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -2188,7 +2323,11 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
-  ExpectedSnippet<int> snippets[] = {
+  int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
+
+  // clang-format off
+  ExpectedSnippet<InstanceType> snippets[] = {
       {"var x = 0;\n"
        "label: {\n"
        "  x = x + 1;\n"
@@ -2198,8 +2337,9 @@
        "return x;",
        2 * kPointerSize,
        1,
-       16,
+       17,
        {
+           B(StackCheck),      //
            B(LdaZero),         //
            B(Star), R(0),      //
            B(Star), R(1),      //
@@ -2222,8 +2362,9 @@
        "return sum;",
        5 * kPointerSize,
        1,
-       72,
+       75,
        {
+           B(StackCheck),           //
            B(LdaZero),              //
            B(Star), R(0),           //
            B(LdaZero),              //
@@ -2232,14 +2373,16 @@
            B(Star), R(3),           //
            B(LdaSmi8), U8(10),      //
            B(TestLessThan), R(3),   //
-           B(JumpIfFalse), U8(55),  //
+           B(JumpIfFalse), U8(57),  //
+           B(StackCheck),           //
            B(LdaZero),              //
            B(Star), R(2),           //
            B(Ldar), R(2),           //
            B(Star), R(3),           //
            B(LdaSmi8), U8(3),       //
            B(TestLessThan), R(3),   //
-           B(JumpIfFalse), U8(34),  //
+           B(JumpIfFalse), U8(35),  //
+           B(StackCheck),           //
            B(Ldar), R(0),           //
            B(ToNumber),             //
            B(Inc),                  //
@@ -2257,16 +2400,128 @@
            B(ToNumber),             //
            B(Inc),                  //
            B(Star), R(2),           //
-           B(Jump), U8(-40),        //
+           B(Jump), U8(-41),        //
            B(Ldar), R(1),           //
            B(ToNumber),             //
            B(Inc),                  //
            B(Star), R(1),           //
-           B(Jump), U8(-61),        //
+           B(Jump), U8(-63),        //
            B(Ldar), R(0),           //
            B(Return),               //
        }},
+      {"outer: {\n"
+       "  let y = 10;"
+       "  function f() { return y; }\n"
+       "  break outer;\n"
+       "}\n",
+       5 * kPointerSize,
+       1,
+       51,
+       {
+           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(LdaSmi8), 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),                                                        //
+       },
+       3,
+       {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+      {"let x = 1;\n"
+       "outer: {\n"
+       "  inner: {\n"
+       "   let y = 2;\n"
+       "    function f() { return x + y; }\n"
+       "    if (y) break outer;\n"
+       "    y = 3;\n"
+       "  }\n"
+       "}\n"
+       "x = 4;",
+       6 * kPointerSize,
+       1,
+       131,
+       {
+           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),    //
+           U8(1),                                                            //
+           B(PushContext), R(2),                                             //
+           B(LdaTheHole),                                                    //
+           B(StaContextSlot), R(context), U8(4),                             //
+           B(StackCheck),                                                    //
+           B(LdaSmi8), 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(LdaSmi8), 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(LdaSmi8), 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(LdaSmi8), 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),                                                        //
+       },
+       5,
+       {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -2280,14 +2535,19 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
-  ExpectedSnippet<int> snippets[] = {
+  int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
+
+  // clang-format off
+  ExpectedSnippet<InstanceType> snippets[] = {
       {"var x = 0;\n"
        "while (false) { x = 99; break; continue; }\n"
        "return x;",
        1 * kPointerSize,
        1,
-       4,
+       5,
        {
+           B(StackCheck),  //
            B(LdaZero),     //
            B(Star), R(0),  //
            B(Return)       //
@@ -2299,8 +2559,9 @@
        "return x;",
        1 * kPointerSize,
        1,
-       4,
+       5,
        {
+           B(StackCheck),  //
            B(LdaZero),     //
            B(Star), R(0),  //
            B(Return),      //
@@ -2317,8 +2578,9 @@
        "return y;",
        3 * kPointerSize,
        1,
-       64,
+       66,
        {
+           B(StackCheck),           //
            B(LdaZero),              //
            B(Star), R(0),           //
            B(LdaSmi8), U8(1),       //
@@ -2327,7 +2589,8 @@
            B(Star), R(2),           //
            B(LdaSmi8), U8(10),      //
            B(TestLessThan), R(2),   //
-           B(JumpIfFalse), U8(46),  //
+           B(JumpIfFalse), U8(47),  //
+           B(StackCheck),           //
            B(Ldar), R(1),           //
            B(Star), R(2),           //
            B(LdaSmi8), U8(12),      //
@@ -2342,14 +2605,14 @@
            B(LdaSmi8), U8(3),       //
            B(TestEqual), R(2),      //
            B(JumpIfFalse), U8(4),   //
-           B(Jump), U8(-38),        //
+           B(Jump), U8(-39),        //
            B(Ldar), R(0),           //
            B(Star), R(2),           //
            B(LdaSmi8), U8(4),       //
            B(TestEqual), R(2),      //
            B(JumpIfFalse), U8(4),   //
            B(Jump), U8(4),          //
-           B(Jump), U8(-52),        //
+           B(Jump), U8(-53),        //
            B(Ldar), R(1),           //
            B(Return),               //
        },
@@ -2366,16 +2629,18 @@
        "return i;",
        2 * kPointerSize,
        1,
-       77,
+       79,
        {
+           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(-9),        //
+           B(Jump), U8(-10),       //
            B(Ldar), R(0),          //
            B(Star), R(1),          //
            B(LdaSmi8), U8(3),      //
@@ -2393,7 +2658,7 @@
            B(LdaSmi8), U8(10),     //
            B(TestEqual), R(1),     //
            B(JumpIfFalse), U8(4),  //
-           B(Jump), U8(-45),       //
+           B(Jump), U8(-46),       //
            B(Ldar), R(0),          //
            B(Star), R(1),          //
            B(LdaSmi8), U8(5),      //
@@ -2405,7 +2670,7 @@
            B(LdaSmi8), U8(1),      //
            B(Add), R(1),           //
            B(Star), R(0),          //
-           B(Jump), U8(-69),       //
+           B(Jump), U8(-70),       //
            B(Ldar), R(0),          //
            B(Return),              //
        },
@@ -2422,15 +2687,18 @@
        "return i;",
        2 * kPointerSize,
        1,
-       54,
+       57,
        {
+           B(StackCheck),           //
            B(LdaZero),              //
            B(Star), R(0),           //
+           B(StackCheck),           //
            B(Ldar), R(0),           //
            B(Star), R(1),           //
            B(LdaSmi8), U8(3),       //
            B(TestLessThan), R(1),   //
-           B(JumpIfFalse), U8(26),  //
+           B(JumpIfFalse), U8(27),  //
+           B(StackCheck),           //
            B(Ldar), R(0),           //
            B(Star), R(1),           //
            B(LdaSmi8), U8(2),       //
@@ -2442,14 +2710,14 @@
            B(LdaSmi8), U8(1),       //
            B(Add), R(1),            //
            B(Star), R(0),           //
-           B(Jump), U8(-32),        //
+           B(Jump), U8(-33),        //
            B(Ldar), R(0),           //
            B(Star), R(1),           //
            B(LdaSmi8), U8(1),       //
            B(Add), R(1),            //
            B(Star), R(0),           //
            B(Jump), U8(4),          //
-           B(Jump), U8(-46),        //
+           B(Jump), U8(-48),        //
            B(Ldar), R(0),           //
            B(Return),               //
        },
@@ -2463,14 +2731,16 @@
        "return y;",
        3 * kPointerSize,
        1,
-       37,
+       39,
        {
+           B(StackCheck),                    //
            B(LdaSmi8), U8(10),               //
            B(Star), R(0),                    //
            B(LdaSmi8), U8(1),                //
            B(Star), R(1),                    //
            B(Ldar), R(0),                    //
-           B(JumpIfToBooleanFalse), U8(24),  //
+           B(JumpIfToBooleanFalse), U8(25),  //
+           B(StackCheck),                    //
            B(Ldar), R(1),                    //
            B(Star), R(2),                    //
            B(LdaSmi8), U8(12),               //
@@ -2481,7 +2751,7 @@
            B(LdaSmi8), U8(1),                //
            B(Sub), R(2),                     //
            B(Star), R(0),                    //
-           B(Jump), U8(-24),                 //
+           B(Jump), U8(-25),                 //
            B(Ldar), R(1),                    //
            B(Return),                        //
        },
@@ -2496,12 +2766,14 @@
        "return y;",
        3 * kPointerSize,
        1,
-       64,
+       66,
        {
+           B(StackCheck),           //
            B(LdaZero),              //
            B(Star), R(0),           //
            B(LdaSmi8), U8(1),       //
            B(Star), R(1),           //
+           B(StackCheck),           //
            B(Ldar), R(1),           //
            B(Star), R(2),           //
            B(LdaSmi8), U8(10),      //
@@ -2528,7 +2800,7 @@
            B(Star), R(2),           //
            B(LdaSmi8), U8(10),      //
            B(TestLessThan), R(2),   //
-           B(JumpIfTrue), U8(-52),  //
+           B(JumpIfTrue), U8(-53),  //
            B(Ldar), R(1),           //
            B(Return),               //
        },
@@ -2542,12 +2814,14 @@
        "return y;",
        3 * kPointerSize,
        1,
-       35,
+       37,
        {
+           B(StackCheck),                    //
            B(LdaSmi8), U8(10),               //
            B(Star), R(0),                    //
            B(LdaSmi8), U8(1),                //
            B(Star), R(1),                    //
+           B(StackCheck),                    //
            B(Ldar), R(1),                    //
            B(Star), R(2),                    //
            B(LdaSmi8), U8(12),               //
@@ -2559,7 +2833,7 @@
            B(Sub), R(2),                     //
            B(Star), R(0),                    //
            B(Ldar), R(0),                    //
-           B(JumpIfToBooleanTrue), U8(-22),  //
+           B(JumpIfToBooleanTrue), U8(-23),  //
            B(Ldar), R(1),                    //
            B(Return),                        //
        },
@@ -2574,12 +2848,14 @@
        "return y;",
        3 * kPointerSize,
        1,
-       52,
+       54,
        {
+           B(StackCheck),          //
            B(LdaZero),             //
            B(Star), R(0),          //
            B(LdaSmi8), U8(1),      //
            B(Star), R(1),          //
+           B(StackCheck),          //
            B(Ldar), R(1),          //
            B(Star), R(2),          //
            B(LdaSmi8), U8(10),     //
@@ -2615,12 +2891,14 @@
        "return y;",
        3 * kPointerSize,
        1,
-       54,
+       56,
        {
+           B(StackCheck),          //
            B(LdaZero),             //
            B(Star), R(0),          //
            B(LdaSmi8), U8(1),      //
            B(Star), R(1),          //
+           B(StackCheck),          //
            B(Ldar), R(1),          //
            B(Star), R(2),          //
            B(LdaSmi8), U8(10),     //
@@ -2641,8 +2919,8 @@
            B(LdaSmi8), U8(6),      //
            B(TestEqual), R(2),     //
            B(JumpIfFalse), U8(4),  //
-           B(Jump), U8(-40),       //
-           B(Jump), U8(-42),       //
+           B(Jump), U8(-41),       //
+           B(Jump), U8(-43),       //
            B(Ldar), R(1),          //
            B(Return),              //
        },
@@ -2655,10 +2933,12 @@
        "}",
        2 * kPointerSize,
        1,
-       41,
+       43,
        {
+           B(StackCheck),          //
            B(LdaZero),             //
            B(Star), R(0),          //
+           B(StackCheck),          //
            B(Ldar), R(0),          //
            B(Star), R(1),          //
            B(LdaSmi8), U8(1),      //
@@ -2670,13 +2950,13 @@
            B(LdaSmi8), U8(2),      //
            B(TestEqual), R(1),     //
            B(JumpIfFalse), U8(4),  //
-           B(Jump), U8(-22),       //
+           B(Jump), U8(-23),       //
            B(Ldar), R(0),          //
            B(Star), R(1),          //
            B(LdaSmi8), U8(1),      //
            B(Add), R(1),           //
            B(Star), R(0),          //
-           B(Jump), U8(-34),       //
+           B(Jump), U8(-35),       //
            B(LdaUndefined),        //
            B(Return),              //
        },
@@ -2688,10 +2968,12 @@
        "}",
        2 * kPointerSize,
        1,
-       41,
+       43,
        {
+           B(StackCheck),          //
            B(LdaZero),             //
            B(Star), R(0),          //
+           B(StackCheck),          //
            B(Ldar), R(0),          //
            B(Star), R(1),          //
            B(LdaSmi8), U8(1),      //
@@ -2703,13 +2985,13 @@
            B(LdaSmi8), U8(2),      //
            B(TestEqual), R(1),     //
            B(JumpIfFalse), U8(4),  //
-           B(Jump), U8(-22),       //
+           B(Jump), U8(-23),       //
            B(Ldar), R(0),          //
            B(Star), R(1),          //
            B(LdaSmi8), U8(1),      //
            B(Add), R(1),           //
            B(Star), R(0),          //
-           B(Jump), U8(-34),       //
+           B(Jump), U8(-35),       //
            B(LdaUndefined),        //
            B(Return),              //
        },
@@ -2721,10 +3003,12 @@
        "}",
        2 * kPointerSize,
        1,
-       41,
+       43,
        {
+           B(StackCheck),          //
            B(LdaZero),             //
            B(Star), R(0),          //
+           B(StackCheck),          //
            B(Ldar), R(0),          //
            B(Star), R(1),          //
            B(LdaSmi8), U8(1),      //
@@ -2742,7 +3026,7 @@
            B(LdaSmi8), U8(1),      //
            B(Add), R(1),           //
            B(Star), R(0),          //
-           B(Jump), U8(-34),       //
+           B(Jump), U8(-35),       //
            B(LdaUndefined),        //
            B(Return),              //
        },
@@ -2753,10 +3037,12 @@
        "}",
        2 * kPointerSize,
        1,
-       41,
+       43,
        {
+           B(StackCheck),          //
            B(LdaZero),             //
            B(Star), R(0),          //
+           B(StackCheck),          //
            B(Ldar), R(0),          //
            B(Star), R(1),          //
            B(LdaSmi8), U8(1),      //
@@ -2774,7 +3060,7 @@
            B(LdaSmi8), U8(1),      //
            B(Add), R(1),           //
            B(Star), R(0),          //
-           B(Jump), U8(-34),       //
+           B(Jump), U8(-35),       //
            B(LdaUndefined),        //
            B(Return),              //
        },
@@ -2786,8 +3072,9 @@
        "}",
        3 * kPointerSize,
        1,
-       42,
+       44,
        {
+           B(StackCheck),           //
            B(LdaZero),              //
            B(Star), R(0),           //
            B(LdaZero),              //
@@ -2796,7 +3083,8 @@
            B(Star), R(2),           //
            B(LdaSmi8), U8(100),     //
            B(TestLessThan), R(2),   //
-           B(JumpIfFalse), U8(26),  //
+           B(JumpIfFalse), U8(27),  //
+           B(StackCheck),           //
            B(Ldar), R(0),           //
            B(Star), R(2),           //
            B(LdaSmi8), U8(1),       //
@@ -2808,7 +3096,7 @@
            B(LdaSmi8), U8(1),       //
            B(Add), R(2),            //
            B(Star), R(1),           //
-           B(Jump), U8(-32),        //
+           B(Jump), U8(-33),        //
            B(LdaUndefined),         //
            B(Return),               //
        },
@@ -2820,14 +3108,16 @@
        "return y;",
        3 * kPointerSize,
        1,
-       33,
+       35,
        {
+           B(StackCheck),                    //
            B(LdaSmi8), U8(1),                //
            B(Star), R(0),                    //
            B(LdaSmi8), U8(10),               //
            B(Star), R(1),                    //
            B(Ldar), R(1),                    //
-           B(JumpIfToBooleanFalse), U8(20),  //
+           B(JumpIfToBooleanFalse), U8(21),  //
+           B(StackCheck),                    //
            B(Ldar), R(0),                    //
            B(Star), R(2),                    //
            B(LdaSmi8), U8(12),               //
@@ -2837,7 +3127,7 @@
            B(ToNumber),                      //
            B(Dec),                           //
            B(Star), R(1),                    //
-           B(Jump), U8(-20),                 //
+           B(Jump), U8(-21),                 //
            B(Ldar), R(0),                    //
            B(Return),                        //
        },
@@ -2849,8 +3139,9 @@
        "return x;",
        2 * kPointerSize,
        1,
-       9,
+       10,
        {
+           B(StackCheck),  //
            B(LdaZero),     //
            B(Star), R(0),  //
            B(LdaZero),     //
@@ -2867,12 +3158,14 @@
        "return x;",
        3 * kPointerSize,
        1,
-       37,
+       39,
        {
+           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(LdaSmi8), U8(1),      //
@@ -2887,12 +3180,83 @@
            B(ToNumber),            //
            B(Inc),                 //
            B(Star), R(1),          //
-           B(Jump), U8(-26),       //
+           B(Jump), U8(-27),       //
            B(Ldar), R(0),          //
            B(Return),              //
        },
        0},
+      {"var a = 0;\n"
+       "while (a) {\n"
+       "  { \n"
+       "   let z = 1;\n"
+       "   function f() { z = 2; }\n"
+       "   if (z) continue;\n"
+       "   z++;\n"
+       "  }\n"
+       "}\n",
+       7 * kPointerSize,
+       1,
+       118,
+       {
+           B(StackCheck),                                                    //
+           B(LdaZero),                                                       //
+           B(Star), R(1),                                                    //
+           B(Ldar), R(1),                                                    //
+           B(JumpIfToBooleanFalse), U8(110),                                 //
+           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(LdaSmi8), 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(6),                                   //
+           B(PopContext), R(3),                                              //
+           B(Jump), U8(-67),                                                 //
+           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(-110),                                                //
+           B(LdaUndefined),                                                  //
+           B(Return),                                                        //
+       },
+       4,
+       {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -2907,6 +3271,7 @@
   BytecodeGeneratorHelper helper;
 
   int constant_count = 0;
+  // clang-format off
   ExpectedSnippet<Handle<Object>, 316> snippets[] = {
       {
        REPEAT_256(SPACE, "var x = 0.1;")
@@ -2920,8 +3285,9 @@
        "return 3;",
        kPointerSize * 3,
        1,
-       1359,
+       1361,
        {
+           B(StackCheck),                         //
 #define L(c) B(LdaConstant), U8(c), B(Star), R(0)
            REPEAT_256(COMMA, L(constant_count++)),
 #undef L
@@ -2937,6 +3303,7 @@
            B(LdaSmi8), U8(3),                     //
            B(TestLessThan), R(2),                 //
            B(JumpIfFalseConstantWide), U16(313),  //
+           B(StackCheck),                         //
            B(Ldar), R(1),                         //
            B(Star), R(2),                         //
            B(LdaSmi8), U8(1),                     //
@@ -2954,7 +3321,7 @@
            B(Star), R(2),                         //
            B(Inc),                                //
            B(Star), R(1),                         //
-           B(Jump), U8(-47),                      //
+           B(Jump), U8(-48),                      //
            B(LdaSmi8), U8(3),                     //
            B(Return)                              //
        },
@@ -2967,9 +3334,11 @@
         REPEAT_8(COMMA, S(0.4)),
 #undef S
 #define N(x) CcTest::i_isolate()->factory()->NewNumberFromInt(x)
-           N(6), N(41), N(13), N(17)
+           N(6), N(42), N(13), N(17)
 #undef N
-       }}};
+       }}
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -2983,6 +3352,7 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"var x = 0;"
        "while (x != 10) {"
@@ -2991,8 +3361,9 @@
        "return x;",
        2 * kPointerSize,
        1,
-       29,
+       31,
        {
+           B(StackCheck),           //
            B(LdaZero),              //
            B(Star), R(0),           //
            B(Ldar), R(0),           //
@@ -3000,13 +3371,14 @@
            B(LdaSmi8), U8(10),      //
            B(TestEqual), R(1),      //
            B(LogicalNot),           //
-           B(JumpIfFalse), U8(14),  //
+           B(JumpIfFalse), U8(15),  //
+           B(StackCheck),           //
            B(Ldar), R(0),           //
            B(Star), R(1),           //
            B(LdaSmi8), U8(10),      //
            B(Add), R(1),            //
            B(Star), R(0),           //
-           B(Jump), U8(-21),        //
+           B(Jump), U8(-22),        //
            B(Ldar), R(0),           //
            B(Return),               //
        },
@@ -3018,28 +3390,31 @@
        "return x;",
        2 * kPointerSize,
        1,
-       20,
+       22,
        {
-           B(LdaFalse),            //
-           B(Star), R(0),          //
-           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(-12),  //
-           B(Ldar), R(0),          //
-           B(Return),              //
+           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),               //
        },
        0},
       {"var x = 101;"
        "return void(x * 3);",
        2 * kPointerSize,
        1,
-       12,
+       13,
        {
+           B(StackCheck),        //
            B(LdaSmi8), U8(101),  //
            B(Star), R(0),        //
            B(Star), R(1),        //
@@ -3054,8 +3429,9 @@
        "return y;",
        4 * kPointerSize,
        1,
-       20,
+       21,
        {
+           B(StackCheck),          //
            B(LdaConstant), U8(0),  //
            B(Star), R(0),          //
            B(Star), R(2),          //
@@ -3074,8 +3450,9 @@
        "return ~x;",
        2 * kPointerSize,
        1,
-       11,
+       12,
        {
+           B(StackCheck),        //
            B(LdaSmi8), U8(13),   //
            B(Star), R(0),        //
            B(Star), R(1),        //
@@ -3088,8 +3465,9 @@
        "return +x;",
        2 * kPointerSize,
        1,
-       11,
+       12,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(13),  //
            B(Star), R(0),       //
            B(Star), R(1),       //
@@ -3102,8 +3480,9 @@
        "return -x;",
        2 * kPointerSize,
        1,
-       11,
+       12,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(13),  //
            B(Star), R(0),       //
            B(Star), R(1),       //
@@ -3111,7 +3490,9 @@
            B(Mul), R(1),        //
            B(Return),           //
        },
-       0}};
+       0}
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -3132,6 +3513,7 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"function f() {\n"
        " var x = 13;\n"
@@ -3139,8 +3521,9 @@
        "}; f();",
        kPointerSize,
        1,
-       6,
+       7,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(13),  //
            B(Star), R(0),       //
            B(TypeOf),           //
@@ -3152,32 +3535,17 @@
        "}; f();",
        0,
        1,
-       5,
+       6,
        {
-           B(LdaGlobalInsideTypeofSloppy), U8(0),                       //
-                                           U8(vector->GetIndex(slot)),  //
-           B(TypeOf),                                                   //
-           B(Return),                                                   //
-       },
-       1,
-       {"x"}},
-      {"var x = 13;\n"
-       "function f() {\n"
-       " 'use strict';\n"
-       " return typeof(x);\n"
-       "}; f();",
-       0,
-       1,
-       5,
-       {
-           B(LdaGlobalInsideTypeofStrict), U8(0),                       //
-                                           U8(vector->GetIndex(slot)),  //
-           B(TypeOf),                                                   //
-           B(Return),                                                   //
+           B(StackCheck),                                                //
+           B(LdaGlobalInsideTypeof), U8(0), U8(vector->GetIndex(slot)),  //
+           B(TypeOf),                                                    //
+           B(Return),                                                    //
        },
        1,
        {"x"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -3194,63 +3562,65 @@
   int deep_elements_flags =
       ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
   int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
   int first_context_slot = Context::MIN_CONTEXT_SLOTS;
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"var a = {x:13, y:14}; return delete a.x;",
        2 * kPointerSize,
        1,
-       13,
+       16,
        {
-           B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
-           B(Star), R(0),                                                  //
-           B(Star), R(1),                                                  //
-           B(LdaConstant), U8(1),                                          //
-           B(DeletePropertySloppy), R(1),                                  //
-           B(Return)
-       },
+        B(StackCheck),                                                  //
+        B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
+        B(Star), R(1),                                                  //
+        B(Star), R(0),                                                  //
+        B(Star), R(1),                                                  //
+        B(LdaConstant), U8(1),                                          //
+        B(DeletePropertySloppy), R(1),                                  //
+        B(Return)},
        2,
        {InstanceType::FIXED_ARRAY_TYPE,
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
       {"'use strict'; var a = {x:13, y:14}; return delete a.x;",
        2 * kPointerSize,
        1,
-       13,
-       {
-           B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
-           B(Star), R(0),                                                  //
-           B(Star), R(1),                                                  //
-           B(LdaConstant), U8(1),                                          //
-           B(DeletePropertyStrict), R(1),                                  //
-           B(Return)
-       },
+       16,
+       {B(StackCheck),                                                  //
+        B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
+        B(Star), R(1),                                                  //
+        B(Star), R(0),                                                  //
+        B(Star), R(1),                                                  //
+        B(LdaConstant), U8(1),                                          //
+        B(DeletePropertyStrict), R(1),                                  //
+        B(Return)},
        2,
        {InstanceType::FIXED_ARRAY_TYPE,
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
       {"var a = {1:13, 2:14}; return delete a[2];",
        2 * kPointerSize,
        1,
-       13,
-       {
-           B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
-           B(Star), R(0),                                                  //
-           B(Star), R(1),                                                  //
-           B(LdaSmi8), U8(2),                                              //
-           B(DeletePropertySloppy), R(1),                                  //
-           B(Return)
-       },
+       16,
+       {B(StackCheck),                                                  //
+        B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
+        B(Star), R(1),                                                  //
+        B(Star), R(0),                                                  //
+        B(Star), R(1),                                                  //
+        B(LdaSmi8), U8(2),                                              //
+        B(DeletePropertySloppy), R(1),                                  //
+        B(Return)},
        1,
        {InstanceType::FIXED_ARRAY_TYPE}},
       {"var a = 10; return delete a;",
        1 * kPointerSize,
        1,
-       6,
-       {
-           B(LdaSmi8), U8(10),  //
-           B(Star), R(0),       //
-           B(LdaFalse),         //
-           B(Return)
-        },
+       7,
+       {B(StackCheck),       //
+        B(LdaSmi8), U8(10),  //
+        B(Star), R(0),       //
+        B(LdaFalse),         //
+        B(Return)},
        0},
       {"'use strict';"
        "var a = {1:10};"
@@ -3258,33 +3628,33 @@
        "return delete a[1];",
        2 * kPointerSize,
        1,
-       27,
-       {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext),              //
-                            R(closure), U8(1),                             //
-           B(PushContext), R(0),                                           //
-           B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
-           B(StaContextSlot), R(0), U8(first_context_slot),                //
-           B(CreateClosure), U8(1), U8(0),                                 //
-           B(LdaContextSlot), R(0), U8(first_context_slot),                //
-           B(Star), R(1),                                                  //
-           B(LdaSmi8), U8(1),                                              //
-           B(DeletePropertyStrict), R(1),                                  //
-           B(Return)
-       },
+       30,
+       {B(CallRuntime), U16(Runtime::kNewFunctionContext),              //
+        /*           */ R(closure), U8(1),                              //
+        B(PushContext), R(0),                                           //
+        B(StackCheck),                                                  //
+        B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
+        B(Star), R(1),                                                  //
+        B(StaContextSlot), R(context), U8(first_context_slot),          //
+        B(CreateClosure), U8(1), U8(0),                                 //
+        B(LdaContextSlot), R(context), U8(first_context_slot),          //
+        B(Star), R(1),                                                  //
+        B(LdaSmi8), U8(1),                                              //
+        B(DeletePropertyStrict), R(1),                                  //
+        B(Return)},
        2,
        {InstanceType::FIXED_ARRAY_TYPE,
         InstanceType::SHARED_FUNCTION_INFO_TYPE}},
       {"return delete 'test';",
        0 * kPointerSize,
        1,
-       2,
-       {
-           B(LdaTrue),  //
-           B(Return)
-       },
+       3,
+       {B(StackCheck),  //
+        B(LdaTrue),  //
+        B(Return)},
        0},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -3299,7 +3669,7 @@
   BytecodeGeneratorHelper helper;
   Zone zone;
 
-  int context = Register::function_context().index();
+  int context = Register::current_context().index();
   int native_context_index = Context::NATIVE_CONTEXT_INDEX;
   int global_context_index = Context::EXTENSION_INDEX;
   FeedbackVectorSpec feedback_spec(&zone);
@@ -3308,12 +3678,14 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"var a = {x:13, y:14};\n function f() { return delete a.x; };\n f();",
        1 * kPointerSize,
        1,
-       10,
-       {B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)),  //
+       11,
+       {B(StackCheck),                                          //
+        B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)),  //
         B(Star), R(0),                                          //
         B(LdaConstant), U8(1),                                  //
         B(DeletePropertySloppy), R(0),                          //
@@ -3325,8 +3697,9 @@
        "function f() {'use strict'; return delete a[1];};\n f();",
        1 * kPointerSize,
        1,
-       10,
-       {B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)),  //
+       11,
+       {B(StackCheck),                                          //
+        B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)),  //
         B(Star), R(0),                                          //
         B(LdaSmi8), U8(1),                                      //
         B(DeletePropertyStrict), R(0),                          //
@@ -3336,8 +3709,9 @@
       {"var a = {x:13, y:14};\n function f() { return delete a; };\n f();",
        2 * kPointerSize,
        1,
-       15,
-       {B(LdaContextSlot), R(context), U8(native_context_index),  //
+       16,
+       {B(StackCheck),                                            //
+        B(LdaContextSlot), R(context), U8(native_context_index),  //
         B(Star), R(0),                                            //
         B(LdaContextSlot), R(0), U8(global_context_index),        //
         B(Star), R(1),                                            //
@@ -3349,8 +3723,9 @@
       {"b = 30;\n function f() { return delete b; };\n f();",
        2 * kPointerSize,
        1,
-       15,
-       {B(LdaContextSlot), R(context), U8(native_context_index),  //
+       16,
+       {B(StackCheck),                                            //
+        B(LdaContextSlot), R(context), U8(native_context_index),  //
         B(Star), R(0),                                            //
         B(LdaContextSlot), R(0), U8(global_context_index),        //
         B(Star), R(1),                                            //
@@ -3358,7 +3733,9 @@
         B(DeletePropertySloppy), R(1),                            //
         B(Return)},
        1,
-       {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}};
+       {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -3379,12 +3756,14 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"return function(){ }",
        0,
        1,
-       4,
+       5,
        {
+           B(StackCheck),                   //
            B(CreateClosure), U8(0), U8(0),  //
            B(Return)                        //
        },
@@ -3393,13 +3772,14 @@
       {"return (function(){ })()",
        2 * kPointerSize,
        1,
-       14,
+       15,
        {
+           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(0), U8(vector->GetIndex(slot)),  //
+           B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)),  //
            B(Return)                                                //
        },
        1,
@@ -3407,20 +3787,22 @@
       {"return (function(x){ return x; })(1)",
        3 * kPointerSize,
        1,
-       18,
+       19,
        {
+           B(StackCheck),                                           //
            B(LdaUndefined),                                         //
            B(Star), R(1),                                           //
            B(CreateClosure), U8(0), U8(0),                          //
            B(Star), R(0),                                           //
            B(LdaSmi8), U8(1),                                       //
            B(Star), R(2),                                           //
-           B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)),  //
+           B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot)),  //
            B(Return)                                                //
        },
        1,
        {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -3443,12 +3825,14 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"return /ab+d/;",
        0 * kPointerSize,
        1,
-       5,
+       6,
        {
+           B(StackCheck),                                //
            B(CreateRegExpLiteral), U8(0), U8(0), U8(0),  //
            B(Return),                                    //
        },
@@ -3457,8 +3841,9 @@
       {"return /(\\w+)\\s(\\w+)/i;",
        0 * kPointerSize,
        1,
-       5,
+       6,
        {
+           B(StackCheck),                                      //
            B(CreateRegExpLiteral), U8(0), U8(0), U8(i_flags),  //
            B(Return),                                          //
        },
@@ -3467,20 +3852,22 @@
       {"return /ab+d/.exec('abdd');",
        3 * kPointerSize,
        1,
-       22,
+       23,
        {
+           B(StackCheck),                                              //
            B(CreateRegExpLiteral), U8(0), U8(0), U8(0),                //
            B(Star), R(1),                                              //
-           B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)),  //
+           B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot2)),  //
            B(Star), R(0),                                              //
            B(LdaConstant), U8(2),                                      //
            B(Star), R(2),                                              //
-           B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)),    //
+           B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)),    //
            B(Return),                                                  //
        },
        3,
        {"ab+d", "exec", "abdd"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -3497,12 +3884,14 @@
 
   int wide_idx = 0;
 
+  // clang-format off
   ExpectedSnippet<InstanceType, 257> snippets[] = {
       {"var a;" REPEAT_256(SPACE, "a = 1.23;") "return /ab+d/;",
        1 * kPointerSize,
        1,
-       1031,
+       1032,
        {
+           B(StackCheck),                                        //
            REPEAT_256(COMMA,                                     //
              B(LdaConstant), U8(wide_idx++),                     //
              B(Star), R(0)),                                     //
@@ -3513,6 +3902,7 @@
        {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -3538,12 +3928,14 @@
   int simple_flags =
       ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
   int deep_elements_flags = ArrayLiteral::kDisableMementos;
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"return [ 1, 2 ];",
        0,
        1,
-       5,
+       6,
        {
+           B(StackCheck),                                          //
            B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags),  //
            B(Return)                                               //
        },
@@ -3552,8 +3944,9 @@
       {"var a = 1; return [ a, a + 1 ];",
        4 * kPointerSize,
        1,
-       38,
+       39,
        {
+           B(StackCheck),                                                   //
            B(LdaSmi8), U8(1),                                               //
            B(Star), R(0),                                                   //
            B(CreateArrayLiteral), U8(0), U8(0), U8(3),                      //
@@ -3577,8 +3970,9 @@
       {"return [ [ 1, 2 ], [ 3 ] ];",
        0,
        1,
-       5,
+       6,
        {
+           B(StackCheck),                                                 //
            B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags),  //
            B(Return)                                                      //
        },
@@ -3587,8 +3981,9 @@
       {"var a = 1; return [ [ a, 2 ], [ a + 2 ] ];",
        6 * kPointerSize,
        1,
-       68,
+       69,
        {
+           B(StackCheck),                                                   //
            B(LdaSmi8), U8(1),                                               //
            B(Star), R(0),                                                   //
            B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags),    //
@@ -3623,6 +4018,7 @@
        {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE,
         InstanceType::FIXED_ARRAY_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -3641,12 +4037,14 @@
   int simple_flags =
       ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
 
+  // clang-format off
   ExpectedSnippet<InstanceType, 257> snippets[] = {
       {"var a;" REPEAT_256(SPACE, "a = 1.23;") "return [ 1 , 2 ];",
        1 * kPointerSize,
        1,
-       1031,
+       1032,
        {
+           B(StackCheck),                                                  //
            REPEAT_256(COMMA,                                               //
              B(LdaConstant), U8(wide_idx++),                               //
              B(Star), R(0)),                                               //
@@ -3657,6 +4055,7 @@
        {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
         InstanceType::FIXED_ARRAY_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -3682,23 +4081,29 @@
                      ObjectLiteral::kDisableMementos;
   int deep_elements_flags =
       ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"return { };",
-       0,
+       kPointerSize,
        1,
-       5,
+       8,
        {
+           B(StackCheck),                                           //
            B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags),  //
+           B(Star), R(0),                                           //
            B(Return)                                                //
        },
        1,
        {InstanceType::FIXED_ARRAY_TYPE}},
       {"return { name: 'string', val: 9.2 };",
-       0,
+       kPointerSize,
        1,
-       5,
+       8,
        {
+           B(StackCheck),                                                  //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
+           B(Star), R(0),                                                  //
            B(Return)                                                       //
        },
        1,
@@ -3706,8 +4111,9 @@
       {"var a = 1; return { name: 'string', val: a };",
        2 * kPointerSize,
        1,
-       19,
+       20,
        {
+           B(StackCheck),                                                  //
            B(LdaSmi8), U8(1),                                              //
            B(Star), R(0),                                                  //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
@@ -3723,8 +4129,9 @@
       {"var a = 1; return { val: a, val: a + 1 };",
        3 * kPointerSize,
        1,
-       25,
+       26,
        {
+           B(StackCheck),                                                  //
            B(LdaSmi8), U8(1),                                              //
            B(Star), R(0),                                                  //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
@@ -3743,8 +4150,9 @@
       {"return { func: function() { } };",
        1 * kPointerSize,
        1,
-       16,
+       17,
        {
+           B(StackCheck),                                                  //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
            B(Star), R(0),                                                  //
            B(CreateClosure), U8(1), U8(0),                                 //
@@ -3753,14 +4161,14 @@
            B(Return),                                                      //
        },
        3,
-       {InstanceType::FIXED_ARRAY_TYPE,
-        InstanceType::SHARED_FUNCTION_INFO_TYPE,
+       {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
       {"return { func(a) { return a; } };",
        1 * kPointerSize,
        1,
-       16,
+       17,
        {
+           B(StackCheck),                                                  //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
            B(Star), R(0),                                                  //
            B(CreateClosure), U8(1), U8(0),                                 //
@@ -3769,26 +4177,27 @@
            B(Return),                                                      //
        },
        3,
-       {InstanceType::FIXED_ARRAY_TYPE,
-        InstanceType::SHARED_FUNCTION_INFO_TYPE,
+       {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
       {"return { get a() { return 2; } };",
-       5 * kPointerSize,
+       6 * kPointerSize,
        1,
-       29,
+       33,
        {
+           B(StackCheck),                                                   //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),   //
            B(Star), R(0),                                                   //
+           B(Mov), R(0), R(1),                                              //
            B(LdaConstant), U8(1),                                           //
-           B(Star), R(1),                                                   //
-           B(CreateClosure), U8(2), U8(0),                                  //
            B(Star), R(2),                                                   //
-           B(LdaNull),                                                      //
+           B(CreateClosure), U8(2), U8(0),                                  //
            B(Star), R(3),                                                   //
-           B(LdaZero),                                                      //
+           B(LdaNull),                                                      //
            B(Star), R(4),                                                   //
+           B(LdaZero),                                                      //
+           B(Star), R(5),                                                   //
            B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked),  //
-                           R(0), U8(5),                                     //
+           /*           */ R(1), U8(5),                                     //
            B(Ldar), R(0),                                                   //
            B(Return),                                                       //
        },
@@ -3797,22 +4206,24 @@
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
         InstanceType::SHARED_FUNCTION_INFO_TYPE}},
       {"return { get a() { return this.x; }, set a(val) { this.x = val } };",
-       5 * kPointerSize,
+       6 * kPointerSize,
        1,
-       31,
+       35,
        {
+           B(StackCheck),                                                   //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),   //
            B(Star), R(0),                                                   //
+           B(Mov), R(0), R(1),                                              //
            B(LdaConstant), U8(1),                                           //
-           B(Star), R(1),                                                   //
-           B(CreateClosure), U8(2), U8(0),                                  //
            B(Star), R(2),                                                   //
-           B(CreateClosure), U8(3), U8(0),                                  //
+           B(CreateClosure), U8(2), U8(0),                                  //
            B(Star), R(3),                                                   //
-           B(LdaZero),                                                      //
+           B(CreateClosure), U8(3), U8(0),                                  //
            B(Star), R(4),                                                   //
+           B(LdaZero),                                                      //
+           B(Star), R(5),                                                   //
            B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked),  //
-                           R(0), U8(5),                                     //
+           /*           */ R(1), U8(5),                                     //
            B(Ldar), R(0),                                                   //
            B(Return),                                                       //
        },
@@ -3822,22 +4233,24 @@
         InstanceType::SHARED_FUNCTION_INFO_TYPE,
         InstanceType::SHARED_FUNCTION_INFO_TYPE}},
       {"return { set b(val) { this.y = val } };",
-       5 * kPointerSize,
+       6 * kPointerSize,
        1,
-       29,
+       33,
        {
+           B(StackCheck),                                                   //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),   //
            B(Star), R(0),                                                   //
+           B(Mov), R(0), R(1),                                              //
            B(LdaConstant), U8(1),                                           //
-           B(Star), R(1),                                                   //
-           B(LdaNull),                                                      //
            B(Star), R(2),                                                   //
-           B(CreateClosure), U8(2), U8(0),                                  //
+           B(LdaNull),                                                      //
            B(Star), R(3),                                                   //
-           B(LdaZero),                                                      //
+           B(CreateClosure), U8(2), U8(0),                                  //
            B(Star), R(4),                                                   //
+           B(LdaZero),                                                      //
+           B(Star), R(5),                                                   //
            B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked),  //
-                           R(0), U8(5),                                     //
+           /*           */ R(1), U8(5),                                     //
            B(Ldar), R(0),                                                   //
            B(Return),                                                       //
        },
@@ -3846,58 +4259,66 @@
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
         InstanceType::SHARED_FUNCTION_INFO_TYPE}},
       {"var a = 1; return { 1: a };",
-       5 * kPointerSize,
+       6 * kPointerSize,
        1,
-       29,
+       33,
        {
+           B(StackCheck),                                                  //
            B(LdaSmi8), U8(1),                                              //
            B(Star), R(0),                                                  //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
            B(Star), R(1),                                                  //
+           B(Mov), R(1), R(2),                                             //
            B(LdaSmi8), U8(1),                                              //
-           B(Star), R(2),                                                  //
-           B(Ldar), R(0),                                                  //
            B(Star), R(3),                                                  //
-           B(LdaZero),                                                     //
+           B(Ldar), R(0),                                                  //
            B(Star), R(4),                                                  //
-           B(CallRuntime), U16(Runtime::kSetProperty), R(1), U8(4),        //
+           B(LdaZero),                                                     //
+           B(Star), R(5),                                                  //
+           B(CallRuntime), U16(Runtime::kSetProperty), R(2), U8(4),        //
            B(Ldar), R(1),                                                  //
            B(Return),                                                      //
        },
        1,
        {InstanceType::FIXED_ARRAY_TYPE}},
       {"return { __proto__: null }",
-       2 * kPointerSize,
+       3 * kPointerSize,
        1,
-       17,
+       21,
        {
+           B(StackCheck),                                                     //
            B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags),            //
            B(Star), R(0),                                                     //
-           B(LdaNull), B(Star), R(1),                                         //
-           B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(0), U8(2),  //
+           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),                                                         //
        },
        1,
        {InstanceType::FIXED_ARRAY_TYPE}},
       {"var a = 'test'; return { [a]: 1 }",
-       5 * kPointerSize,
+       7 * kPointerSize,
        1,
-       30,
+       37,
        {
+           B(StackCheck),                                                     //
            B(LdaConstant), U8(0),                                             //
            B(Star), R(0),                                                     //
            B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags),            //
            B(Star), R(1),                                                     //
+           B(Mov), R(1), R(2),                                                //
            B(Ldar), R(0),                                                     //
            B(ToName),                                                         //
-           B(Star), R(2),                                                     //
-           B(LdaSmi8), U8(1),                                                 //
            B(Star), R(3),                                                     //
-           B(LdaZero),                                                        //
+           B(LdaSmi8), U8(1),                                                 //
            B(Star), R(4),                                                     //
-           B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1),  //
-                           U8(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),                                                         //
        },
@@ -3905,25 +4326,29 @@
        {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
         InstanceType::FIXED_ARRAY_TYPE}},
       {"var a = 'test'; return { val: a, [a]: 1 }",
-       5 * kPointerSize,
+       7 * kPointerSize,
        1,
-       36,
+       43,
        {
+           B(StackCheck),                                                     //
            B(LdaConstant), U8(0),                                             //
            B(Star), R(0),                                                     //
            B(CreateObjectLiteral), U8(1), U8(0), U8(deep_elements_flags),     //
            B(Star), R(1),                                                     //
            B(Ldar), R(0),                                                     //
            B(StoreICSloppy), R(1), U8(2), U8(vector->GetIndex(slot1)),        //
+           B(Mov), R(1), R(2),                                                //
            B(Ldar), R(0),                                                     //
            B(ToName),                                                         //
-           B(Star), R(2),                                                     //
-           B(LdaSmi8), U8(1),                                                 //
            B(Star), R(3),                                                     //
-           B(LdaZero),                                                        //
+           B(LdaSmi8), U8(1),                                                 //
            B(Star), R(4),                                                     //
-           B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1),  //
-                           U8(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),                                                         //
        },
@@ -3932,26 +4357,32 @@
         InstanceType::FIXED_ARRAY_TYPE,
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
       {"var a = 'test'; return { [a]: 1, __proto__: {} }",
-       5 * kPointerSize,
+       7 * kPointerSize,
        1,
-       41,
+       53,
        {
+           B(StackCheck),                                                     //
            B(LdaConstant), U8(0),                                             //
            B(Star), R(0),                                                     //
            B(CreateObjectLiteral), U8(1), U8(1), U8(simple_flags),            //
            B(Star), R(1),                                                     //
+           B(Mov), R(1), R(2),                                                //
            B(Ldar), R(0),                                                     //
            B(ToName),                                                         //
-           B(Star), R(2),                                                     //
-           B(LdaSmi8), U8(1),                                                 //
            B(Star), R(3),                                                     //
-           B(LdaZero),                                                        //
+           B(LdaSmi8), U8(1),                                                 //
            B(Star), R(4),                                                     //
-           B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1),  //
-                           U8(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(13),                      //
-           B(Star), R(2),                                                     //
-           B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2),  //
+           B(Star), R(4),                                                     //
+           B(Star), R(3),                                                     //
+           B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(2), U8(2),  //
            B(Ldar), R(1),                                                     //
            B(Return),                                                         //
        },
@@ -3959,39 +4390,45 @@
        {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
         InstanceType::FIXED_ARRAY_TYPE}},
       {"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };",
-       5 * kPointerSize,
+       7 * kPointerSize,
        1,
-       64,
+       77,
        {
+           B(StackCheck),                                                     //
            B(LdaConstant), U8(0),                                             //
            B(Star), R(0),                                                     //
            B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags),            //
            B(Star), R(1),                                                     //
+           B(Mov), R(1), R(2),                                                //
            B(Ldar), R(0),                                                     //
            B(ToName),                                                         //
-           B(Star), R(2),                                                     //
+           B(Star), R(3),                                                     //
            B(LdaConstant), U8(2),                                             //
-           B(Star), R(3),                                                     //
-           B(LdaZero),                                                        //
            B(Star), R(4),                                                     //
-           B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1),  //
-                           U8(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(2),                                                     //
+           B(Star), R(3),                                                     //
            B(CreateClosure), U8(4), U8(0),                                    //
-           B(Star), R(3),                                                     //
-           B(LdaZero),                                                        //
            B(Star), R(4),                                                     //
+           B(LdaZero),                                                        //
+           B(Star), R(5),                                                     //
            B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked),      //
-                           R(1), U8(4),                                       //
+           /*           */ R(2), U8(4),                                       //
+           B(Mov), R(1), R(2),                                                //
            B(LdaConstant), U8(3),                                             //
-           B(Star), R(2),                                                     //
-           B(CreateClosure), U8(5), U8(0),                                    //
            B(Star), R(3),                                                     //
-           B(LdaZero),                                                        //
+           B(CreateClosure), U8(5), U8(0),                                    //
            B(Star), R(4),                                                     //
+           B(LdaZero),                                                        //
+           B(Star), R(5),                                                     //
            B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked),      //
-                           R(1), U8(4),                                       //
+           /*           */ R(2), U8(4),                                       //
            B(Ldar), R(1),                                                     //
            B(Return),                                                         //
        },
@@ -4003,6 +4440,7 @@
         InstanceType::SHARED_FUNCTION_INFO_TYPE,
         InstanceType::SHARED_FUNCTION_INFO_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4021,24 +4459,28 @@
       ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
   int wide_idx = 0;
 
+  // clang-format off
   ExpectedSnippet<InstanceType, 257> snippets[] = {
       {"var a;" REPEAT_256(SPACE,
                            "a = 1.23;") "return { name: 'string', val: 9.2 };",
-       1 * kPointerSize,
+       2 * kPointerSize,
        1,
-       1031,
+       1034,
        {
+           B(StackCheck),                                        //
            REPEAT_256(COMMA,                                     //
-             B(LdaConstant), U8(wide_idx++),                     //
-             B(Star), R(0)),                                     //
+                      B(LdaConstant), U8(wide_idx++),            //
+                      B(Star), R(0)),                            //
            B(CreateObjectLiteralWide), U16(256), U16(0),         //
-                                       U8(deep_elements_flags),  //
+           /*                       */ U8(deep_elements_flags),  //
+           B(Star), R(1),                                        //
            B(Return)                                             //
        },
        257,
        {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
         InstanceType::FIXED_ARRAY_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4055,17 +4497,19 @@
   int has_function_flags = ObjectLiteral::kFastElements |
                            ObjectLiteral::kHasFunction |
                            ObjectLiteral::kDisableMementos;
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"var a = { func: function() { } };",
        5 * kPointerSize,
        1,
-       48,
+       49,
        {
            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),                                                       //
@@ -4088,6 +4532,7 @@
         InstanceType::SHARED_FUNCTION_INFO_TYPE,
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4101,18 +4546,91 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
-  // TODO(rmcilroy): modify tests when we have real try catch support.
-  ExpectedSnippet<int> snippets[] = {
+  int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
+
+  // clang-format off
+  ExpectedSnippet<const char*> snippets[] = {
       {"try { return 1; } catch(e) { return 2; }",
-       kPointerSize,
+       5 * kPointerSize,
        1,
-       3,
+       40,
        {
-           B(LdaSmi8), U8(1),  //
-           B(Return),          //
+           B(StackCheck),                                                 //
+           B(Mov), R(context), R(1),                                       //
+           B(LdaSmi8), 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(LdaSmi8), U8(2),                                              //
+           B(PopContext), R(0),                                            //
+           B(Return),                                                      //
+           // TODO(mstarzinger): Potential optimization, elide next bytes.
+           B(LdaUndefined),                                                //
+           B(Return),                                                      //
        },
-       0},
+       1,
+       {"e"},
+       1,
+       {{4, 7, 7}}},
+      {"var a; try { a = 1 } catch(e1) {}; try { a = 2 } catch(e2) { a = 3 }",
+       6 * kPointerSize,
+       1,
+       81,
+       {
+           B(StackCheck),                                                 //
+           B(Mov), R(context), R(2),                                       //
+           B(LdaSmi8), 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(LdaSmi8), 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(LdaSmi8), U8(3),                                              //
+           B(Star), R(0),                                                  //
+           B(PopContext), R(1),                                            //
+           B(LdaUndefined),                                                //
+           B(Return),                                                      //
+       },
+       2,
+       {"e1", "e2"},
+       2,
+       {{4, 8, 10}, {41, 45, 47}}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4126,39 +4644,172 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
-  // TODO(rmcilroy): modify tests when we have real try finally support.
-  ExpectedSnippet<int> snippets[] = {
+  int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
+
+  // clang-format off
+  ExpectedSnippet<const char*> snippets[] = {
       {"var a = 1; try { a = 2; } finally { a = 3; }",
-       kPointerSize,
+       4 * kPointerSize,
        1,
-       14,
+       51,
        {
-           B(LdaSmi8), U8(1),  //
-           B(Star), R(0),      //
-           B(LdaSmi8), U8(2),  //
-           B(Star), R(0),      //
-           B(LdaSmi8), U8(3),  //
-           B(Star), R(0),      //
-           B(LdaUndefined),    //
-           B(Return),          //
+           B(StackCheck),                                                  //
+           B(LdaSmi8), U8(1),                                              //
+           B(Star), R(0),                                                  //
+           B(Mov), R(context), R(3),                                       //
+           B(LdaSmi8), U8(2),                                              //
+           B(Star), R(0),                                                  //
+           B(LdaSmi8), 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(LdaSmi8), 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),                                                      //
        },
-       0},
+       0,
+       {},
+       1,
+       {{8, 12, 18}}},
       {"var a = 1; try { a = 2; } catch(e) { a = 20 } finally { a = 3; }",
-       2 * kPointerSize,
+       9 * kPointerSize,
        1,
-       14,
+       88,
        {
-           B(LdaSmi8), U8(1),  //
-           B(Star), R(0),      //
-           B(LdaSmi8), U8(2),  //
-           B(Star), R(0),      //
-           B(LdaSmi8), U8(3),  //
-           B(Star), R(0),      //
-           B(LdaUndefined),    //
-           B(Return),          //
+           B(StackCheck),                                                  //
+           B(LdaSmi8), U8(1),                                              //
+           B(Star), R(0),                                                  //
+           B(Mov), R(context), R(4),                                       //
+           B(Mov), R(context), R(5),                                       //
+           B(LdaSmi8), 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(LdaSmi8), U8(20),                                             //
+           B(Star), R(0),                                                  //
+           B(PopContext), R(1),                                            //
+           B(LdaSmi8), 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(LdaSmi8), 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),                                                      //
        },
-       0},
+       1,
+       {"e"},
+       2,
+       {{8, 49, 55}, {11, 15, 17}}},
+      {"var a; try {"
+       "  try { a = 1 } catch(e) { a = 2 }"
+       "} catch(e) { a = 20 } finally { a = 3; }",
+       10 * kPointerSize,
+       1,
+       121,
+       {
+           B(StackCheck),                                                  //
+           B(Mov), R(context), R(4),                                       //
+           B(Mov), R(context), R(5),                                       //
+           B(Mov), R(context), R(6),                                       //
+           B(LdaSmi8), 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(LdaSmi8), 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(LdaSmi8), U8(20),                                             //
+           B(Star), R(0),                                                  //
+           B(PopContext), R(1),                                            //
+           B(LdaSmi8), 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(LdaSmi8), 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),                                                      //
+       },
+       1,
+       {"e"},
+       3,
+       {{4, 82, 88}, {7, 48, 50}, {10, 14, 16}}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4172,13 +4823,14 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
-  // TODO(rmcilroy): modify tests when we have real try catch support.
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"throw 1;",
        0,
        1,
-       3,
+       4,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Throw),           //
        },
@@ -4186,8 +4838,9 @@
       {"throw 'Error';",
        0,
        1,
-       3,
+       4,
        {
+           B(StackCheck),          //
            B(LdaConstant), U8(0),  //
            B(Throw),               //
        },
@@ -4196,8 +4849,9 @@
       {"var a = 1; if (a) { throw 'Error'; };",
        1 * kPointerSize,
        1,
-       11,
+       12,
        {
+           B(StackCheck),                   //
            B(LdaSmi8), U8(1),               //
            B(Star), R(0),                   //
            B(JumpIfToBooleanFalse), U8(5),  //
@@ -4209,6 +4863,7 @@
        1,
        {"Error"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4231,15 +4886,17 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"function bar() { this.value = 0; }\n"
        "function f() { return new bar(); }\n"
        "f()",
        1 * kPointerSize,
        1,
-       10,
+       11,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)),  //
+           B(StackCheck),                                           //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)),  //
            B(Star), R(0),                                           //
            B(New), R(0), R(0), U8(0),                               //
            B(Return),                                               //
@@ -4251,12 +4908,14 @@
        "f()",
        2 * kPointerSize,
        1,
-       14,
+       17,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)),  //
+           B(StackCheck),                                           //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)),  //
            B(Star), R(0),                                           //
            B(LdaSmi8), U8(3),                                       //
            B(Star), R(1),                                           //
+           B(Ldar), R(0),                                           //
            B(New), R(0), R(1), U8(1),                               //
            B(Return),                                               //
        },
@@ -4272,9 +4931,10 @@
        "f()",
        4 * kPointerSize,
        1,
-       22,
+       25,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)),  //
+           B(StackCheck),                                           //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)),  //
            B(Star), R(0),                                           //
            B(LdaSmi8), U8(3),                                       //
            B(Star), R(1),                                           //
@@ -4282,12 +4942,14 @@
            B(Star), R(2),                                           //
            B(LdaSmi8), U8(5),                                       //
            B(Star), R(3),                                           //
+           B(Ldar), R(0),                                           //
            B(New), R(0), R(1), U8(3),                               //
            B(Return),                                               //
        },
        1,
        {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4309,6 +4971,7 @@
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
   int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
   int new_target = Register::new_target().index();
   int first_context_slot = Context::MIN_CONTEXT_SLOTS;
 
@@ -4318,15 +4981,17 @@
   STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS + 3 + 249 == 256);
   int wide_slot = first_context_slot + 3;
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"var a; return function() { a = 1; };",
        1 * kPointerSize,
        1,
-       11,
+       12,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext),  //
-                           R(closure), U8(1),                  //
+           /*           */ R(closure), U8(1),                  //
            B(PushContext), R(0),                               //
+           B(StackCheck),                                      //
            B(CreateClosure), U8(0), U8(0),                     //
            B(Return),                                          //
        },
@@ -4335,49 +5000,52 @@
       {"var a = 1; return function() { a = 2; };",
        1 * kPointerSize,
        1,
-       16,
+       17,
        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext),  //
-                           R(closure), U8(1),                  //
-           B(PushContext), R(0),                               //
-           B(LdaSmi8), U8(1),                                  //
-           B(StaContextSlot), R(0), U8(first_context_slot),    //
-           B(CreateClosure), U8(0), U8(0),                     //
-           B(Return),                                          //
+           B(CallRuntime), U16(Runtime::kNewFunctionContext),        //
+           /*           */ R(closure), U8(1),                        //
+           B(PushContext), R(0),                                     //
+           B(StackCheck),                                            //
+           B(LdaSmi8), U8(1),                                        //
+           B(StaContextSlot), R(context), U8(first_context_slot),    //
+           B(CreateClosure), U8(0), U8(0),                           //
+           B(Return),                                                //
        },
        1,
        {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
       {"var a = 1; var b = 2; return function() { a = 2; b = 3 };",
        1 * kPointerSize,
        1,
-       21,
+       22,
        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext),    //
-                           R(closure), U8(1),                    //
-           B(PushContext), R(0),                                 //
-           B(LdaSmi8), U8(1),                                    //
-           B(StaContextSlot), R(0), U8(first_context_slot),      //
-           B(LdaSmi8), U8(2),                                    //
-           B(StaContextSlot), R(0), U8(first_context_slot + 1),  //
-           B(CreateClosure), U8(0), U8(0),                       //
-           B(Return),                                            //
+           B(CallRuntime), U16(Runtime::kNewFunctionContext),          //
+           /*           */ R(closure), U8(1),                          //
+           B(PushContext), R(0),                                       //
+           B(StackCheck),                                              //
+           B(LdaSmi8), U8(1),                                          //
+           B(StaContextSlot), R(context), U8(first_context_slot),      //
+           B(LdaSmi8), U8(2),                                          //
+           B(StaContextSlot), R(context), U8(first_context_slot + 1),  //
+           B(CreateClosure), U8(0), U8(0),                             //
+           B(Return),                                                  //
        },
        1,
        {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
       {"var a; (function() { a = 2; })(); return a;",
        3 * kPointerSize,
        1,
-       24,
+       25,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext),       //
-                           R(closure), U8(1),                       //
+           /*           */ 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(0), U8(vector->GetIndex(slot)),  //
-           B(LdaContextSlot), R(0), U8(first_context_slot),         //
+           B(Call), R(1), R(2), U8(1), U8(vector->GetIndex(slot)),  //
+           B(LdaContextSlot), R(context), U8(first_context_slot),   //
            B(Return),                                               //
        },
        1,
@@ -4385,15 +5053,16 @@
       {"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }",
        4 * kPointerSize,
        1,
-       44,
+       47,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext),             //
-                           R(closure), U8(1),                             //
+           /*           */ R(closure), U8(1),                             //
            B(PushContext), R(0),                                          //
            B(LdaTheHole),                                                 //
-           B(StaContextSlot), R(0), U8(first_context_slot),               //
+           B(StaContextSlot), R(context), U8(first_context_slot),         //
+           B(StackCheck),                                                 //
            B(LdaSmi8), U8(1),                                             //
-           B(StaContextSlot), R(0), U8(first_context_slot),               //
+           B(StaContextSlot), R(context), U8(first_context_slot),         //
            B(LdaConstant), U8(0),                                         //
            B(Star), R(2),                                                 //
            B(Ldar), R(closure),                                           //
@@ -4401,10 +5070,11 @@
            B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2),  //
            B(PushContext), R(1),                                          //
            B(LdaTheHole),                                                 //
-           B(StaContextSlot), R(1), U8(first_context_slot),               //
+           B(StaContextSlot), R(context), U8(first_context_slot),         //
            B(LdaSmi8), U8(2),                                             //
-           B(StaContextSlot), R(1), U8(first_context_slot),               //
+           B(StaContextSlot), R(context), U8(first_context_slot),         //
            B(CreateClosure), U8(1), U8(0),                                //
+           B(PopContext), R(0),                                           //
            B(Return),                                                     //
        },
        2,
@@ -4417,33 +5087,35 @@
        "return b",
        3 * kPointerSize,
        1,
-       1041,
+       1042,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),  //
-                           U8(1),                                          //
+           /*           */ U8(1),                                          //
            B(PushContext), R(0),                                           //
            B(Ldar), THIS(1),                                               //
-           B(StaContextSlot), R(0), U8(first_context_slot),                //
+           B(StaContextSlot), R(context), U8(first_context_slot),          //
            B(CreateUnmappedArguments),                                     //
-           B(StaContextSlot), R(0), U8(first_context_slot + 1),            //
+           B(StaContextSlot), R(context), U8(first_context_slot + 1),      //
            B(Ldar), R(new_target),                                         //
-           B(StaContextSlot), R(0), U8(first_context_slot + 2),            //
+           B(StaContextSlot), R(context), U8(first_context_slot + 2),      //
+           B(StackCheck),                                                  //
            REPEAT_249(COMMA,                                               //
                       B(LdaZero),                                          //
-                      B(StaContextSlot), R(0), U8(wide_slot++)),           //
+                      B(StaContextSlot), R(context), U8(wide_slot++)),     //
            B(LdaUndefined),                                                //
            B(Star), R(2),                                                  //
-           B(LdaGlobalStrict), U8(0), U8(1),                               //
+           B(LdaGlobal), U8(0), U8(1),                               //
            B(Star), R(1),                                                  //
-           B(Call), R(1), R(2), U8(0), U8(0),                              //
+           B(Call), R(1), R(2), U8(1), U8(0),                              //
            B(LdaSmi8), U8(100),                                            //
-           B(StaContextSlotWide), R(0), U16(256),                          //
-           B(LdaContextSlotWide), R(0), U16(256),                          //
+           B(StaContextSlotWide), R(context), U16(256),                    //
+           B(LdaContextSlotWide), R(context), U16(256),                    //
            B(Return),                                                      //
        },
        1,
        {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4458,74 +5130,81 @@
   BytecodeGeneratorHelper helper;
 
   int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
   int first_context_slot = Context::MIN_CONTEXT_SLOTS;
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"function f(arg1) { return function() { arg1 = 2; }; }",
        1 * kPointerSize,
        2,
-       16,
+       17,
        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext),  //
-                           R(closure), U8(1),                  //
-           B(PushContext), R(0),                               //
-           B(Ldar), R(helper.kLastParamIndex),                 //
-           B(StaContextSlot), R(0), U8(first_context_slot),    //
-           B(CreateClosure), U8(0), U8(0),                     //
-           B(Return),                                          //
+           B(CallRuntime), U16(Runtime::kNewFunctionContext),        //
+           /*           */ R(closure), U8(1),                        //
+           B(PushContext), R(0),                                     //
+           B(Ldar), R(helper.kLastParamIndex),                       //
+           B(StaContextSlot), R(context), U8(first_context_slot),    //
+           B(StackCheck),                                            //
+           B(CreateClosure), U8(0), U8(0),                           //
+           B(Return),                                                //
        },
        1,
        {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
       {"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }",
        2 * kPointerSize,
        2,
-       21,
+       22,
        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext),  //
-                           R(closure), U8(1),                  //
-           B(PushContext), R(1),                               //
-           B(Ldar), R(helper.kLastParamIndex),                 //
-           B(StaContextSlot), R(1), U8(first_context_slot),    //
-           B(CreateClosure), U8(0), U8(0),                     //
-           B(Star), R(0),                                      //
-           B(LdaContextSlot), R(1), U8(first_context_slot),    //
-           B(Return),                                          //
+           B(CallRuntime), U16(Runtime::kNewFunctionContext),        //
+           /*           */ R(closure), U8(1),                        //
+           B(PushContext), R(1),                                     //
+           B(Ldar), R(helper.kLastParamIndex),                       //
+           B(StaContextSlot), R(context), U8(first_context_slot),    //
+           B(StackCheck),                                            //
+           B(CreateClosure), U8(0), U8(0),                           //
+           B(Star), R(0),                                            //
+           B(LdaContextSlot), R(context), U8(first_context_slot),    //
+           B(Return),                                                //
        },
        1,
        {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
       {"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }",
        1 * kPointerSize,
        5,
-       21,
+       22,
        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext),    //
-                           R(closure), U8(1),                    //
-           B(PushContext), R(0),                                 //
-           B(Ldar), R(helper.kLastParamIndex - 3),               //
-           B(StaContextSlot), R(0), U8(first_context_slot + 1),  //
-           B(Ldar), R(helper.kLastParamIndex -1),                //
-           B(StaContextSlot), R(0), U8(first_context_slot),      //
-           B(CreateClosure), U8(0), U8(0),                       //
-           B(Return),                                            //
+           B(CallRuntime), U16(Runtime::kNewFunctionContext),          //
+           /*           */ R(closure), U8(1),                          //
+           B(PushContext), R(0),                                       //
+           B(Ldar), R(helper.kLastParamIndex - 3),                     //
+           B(StaContextSlot), R(context), U8(first_context_slot + 1),  //
+           B(Ldar), R(helper.kLastParamIndex -1),                      //
+           B(StaContextSlot), R(context), U8(first_context_slot),      //
+           B(StackCheck),                                              //
+           B(CreateClosure), U8(0), U8(0),                             //
+           B(Return),                                                  //
        },
        1,
        {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
       {"function f() { var self = this; return function() { self = 2; }; }",
        1 * kPointerSize,
        1,
-       16,
+       17,
        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext),  //
-                           R(closure), U8(1),                  //
-           B(PushContext), R(0),                               //
-           B(Ldar), R(helper.kLastParamIndex),                 //
-           B(StaContextSlot), R(0), U8(first_context_slot),    //
-           B(CreateClosure), U8(0), U8(0),                     //
-           B(Return),                                          //
+           B(CallRuntime), U16(Runtime::kNewFunctionContext),      //
+           /*           */ R(closure), U8(1),                      //
+           B(PushContext), R(0),                                   //
+           B(StackCheck),                                          //
+           B(Ldar), R(helper.kLastParamIndex),                     //
+           B(StaContextSlot), R(context), U8(first_context_slot),  //
+           B(CreateClosure), U8(0), U8(0),                         //
+           B(Return),                                              //
        },
        1,
        {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4539,9 +5218,10 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
-  int context = Register::function_context().index();
+  int context = Register::current_context().index();
   int first_context_slot = Context::MIN_CONTEXT_SLOTS;
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"function Outer() {"
        "  var outerVar = 1;"
@@ -4553,8 +5233,9 @@
        "var f = new Outer().getInnerFunc();",
        2 * kPointerSize,
        1,
-       20,
+       21,
        {
+           B(StackCheck),                                          //
            B(Ldar), R(context),                                    //
            B(Star), R(0),                                          //
            B(LdaContextSlot), R(0), U8(Context::PREVIOUS_INDEX),   //
@@ -4575,8 +5256,9 @@
        "var f = new Outer().getInnerFunc();",
        2 * kPointerSize,
        1,
-       21,
+       22,
        {
+           B(StackCheck),                                          //
            B(LdaContextSlot), R(context), U8(first_context_slot),  //
            B(Star), R(0),                                          //
            B(Ldar), R(context),                                    //
@@ -4589,6 +5271,7 @@
            B(Return),                                              //
        }},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4615,6 +5298,7 @@
       i::NewTypeFeedbackVector(helper.isolate(), &store_feedback_spec);
 
   int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
   int first_context_slot = Context::MIN_CONTEXT_SLOTS;
 
   int object_literal_flags =
@@ -4622,12 +5306,14 @@
   int array_literal_flags =
       ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"var a = 1; return ++a;",
        1 * kPointerSize,
        1,
-       9,
+       10,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Star), R(0),      //
            B(ToNumber),        //
@@ -4638,8 +5324,9 @@
       {"var a = 1; return a++;",
        2 * kPointerSize,
        1,
-       13,
+       14,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Star), R(0),      //
            B(ToNumber),        //
@@ -4652,8 +5339,9 @@
       {"var a = 1; return --a;",
        1 * kPointerSize,
        1,
-       9,
+       10,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Star), R(0),      //
            B(ToNumber),        //
@@ -4664,8 +5352,9 @@
       {"var a = 1; return a--;",
        2 * kPointerSize,
        1,
-       13,
+       14,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Star), R(0),      //
            B(ToNumber),        //
@@ -4678,12 +5367,14 @@
       {"var a = { val: 1 }; return a.val++;",
        3 * kPointerSize,
        1,
-       23,
+       26,
        {
+           B(StackCheck),                                                   //
            B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags),  //
+           B(Star), R(1),                                                   //
            B(Star), R(0),                                                   //
            B(Star), R(1),                                                   //
-           B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)),       //
+           B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot1)),       //
            B(ToNumber),                                                     //
            B(Star), R(2),                                                   //
            B(Inc),                                                          //
@@ -4697,12 +5388,14 @@
       {"var a = { val: 1 }; return --a.val;",
        2 * kPointerSize,
        1,
-       19,
+       22,
        {
+           B(StackCheck),                                                   //
            B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags),  //
+           B(Star), R(1),                                                   //
            B(Star), R(0),                                                   //
            B(Star), R(1),                                                   //
-           B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)),       //
+           B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot1)),       //
            B(ToNumber),                                                     //
            B(Dec),                                                          //
            B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)),      //
@@ -4714,16 +5407,18 @@
       {"var name = 'var'; var a = { val: 1 }; return a[name]--;",
        5 * kPointerSize,
        1,
-       30,
+       33,
        {
+           B(StackCheck),                                                   //
            B(LdaConstant), U8(0),                                           //
            B(Star), R(0),                                                   //
            B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags),  //
+           B(Star), R(2),                                                   //
            B(Star), R(1),                                                   //
            B(Star), R(2),                                                   //
            B(Ldar), R(0),                                                   //
            B(Star), R(3),                                                   //
-           B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)),         //
+           B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot1)),         //
            B(ToNumber),                                                     //
            B(Star), R(4),                                                   //
            B(Dec),                                                          //
@@ -4737,16 +5432,18 @@
       {"var name = 'var'; var a = { val: 1 }; return ++a[name];",
        4 * kPointerSize,
        1,
-       26,
+       29,
        {
+           B(StackCheck),                                                   //
            B(LdaConstant), U8(0),                                           //
            B(Star), R(0),                                                   //
            B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags),  //
+           B(Star), R(2),                                                   //
            B(Star), R(1),                                                   //
            B(Star), R(2),                                                   //
            B(Ldar), R(0),                                                   //
            B(Star), R(3),                                                   //
-           B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)),         //
+           B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot1)),         //
            B(ToNumber),                                                     //
            B(Inc),                                                          //
            B(KeyedStoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)),  //
@@ -4758,19 +5455,20 @@
       {"var a = 1; var b = function() { return a }; return ++a;",
        2 * kPointerSize,
        1,
-       26,
+       27,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),  //
-                           U8(1),                                          //
+           /*           */ U8(1),                                          //
            B(PushContext), R(1),                                           //
+           B(StackCheck),                                                  //
            B(LdaSmi8), U8(1),                                              //
-           B(StaContextSlot), R(1), U8(first_context_slot),                //
+           B(StaContextSlot), R(context), U8(first_context_slot),          //
            B(CreateClosure), U8(0), U8(0),                                 //
            B(Star), R(0),                                                  //
-           B(LdaContextSlot), R(1), U8(first_context_slot),                //
+           B(LdaContextSlot), R(context), U8(first_context_slot),          //
            B(ToNumber),                                                    //
            B(Inc),                                                         //
-           B(StaContextSlot), R(1), U8(first_context_slot),                //
+           B(StaContextSlot), R(context), U8(first_context_slot),          //
            B(Return),                                                      //
        },
        1,
@@ -4778,20 +5476,21 @@
       {"var a = 1; var b = function() { return a }; return a--;",
        3 * kPointerSize,
        1,
-       30,
+       31,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),  //
-                           U8(1),                                          //
+           /*           */ U8(1),                                          //
            B(PushContext), R(1),                                           //
+           B(StackCheck),                                                  //
            B(LdaSmi8), U8(1),                                              //
-           B(StaContextSlot), R(1), U8(first_context_slot),                //
+           B(StaContextSlot), R(context), U8(first_context_slot),          //
            B(CreateClosure), U8(0), U8(0),                                 //
            B(Star), R(0),                                                  //
-           B(LdaContextSlot), R(1), U8(first_context_slot),                //
+           B(LdaContextSlot), R(context), U8(first_context_slot),          //
            B(ToNumber),                                                    //
            B(Star), R(2),                                                  //
            B(Dec),                                                         //
-           B(StaContextSlot), R(1), U8(first_context_slot),                //
+           B(StaContextSlot), R(context), U8(first_context_slot),          //
            B(Ldar), R(2),                                                  //
            B(Return),                                                      //
        },
@@ -4800,8 +5499,9 @@
       {"var idx = 1; var a = [1, 2]; return a[idx++] = 2;",
        4 * kPointerSize,
        1,
-       27,
+       28,
        {
+           B(StackCheck),                                                  //
            B(LdaSmi8), U8(1),                                              //
            B(Star), R(0),                                                  //
            B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags),   //
@@ -4814,12 +5514,13 @@
            B(Star), R(0),                                                  //
            B(LdaSmi8), U8(2),                                              //
            B(KeyedStoreICSloppy), R(2), R(3),                              //
-                                  U8(store_vector->GetIndex(store_slot)),  //
+           /*                  */ U8(store_vector->GetIndex(store_slot)),  //
            B(Return),                                                      //
        },
        1,
        {InstanceType::FIXED_ARRAY_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4841,13 +5542,15 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"var global = 1;\nfunction f() { return ++global; }\nf()",
        0,
        1,
-       9,
+       10,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(StackCheck),                                            //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)),  //
            B(ToNumber),                                             //
            B(Inc),                                                  //
            B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)),  //
@@ -4858,9 +5561,10 @@
       {"var global = 1;\nfunction f() { return global--; }\nf()",
        1 * kPointerSize,
        1,
-       13,
+       14,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(StackCheck),                                           //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)),  //
            B(ToNumber),                                             //
            B(Star), R(0),                                           //
            B(Dec),                                                  //
@@ -4874,9 +5578,10 @@
        "f()",
        0,
        1,
-       9,
+       10,
        {
-           B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(StackCheck),                                           //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)),  //
            B(ToNumber),                                             //
            B(Dec),                                                  //
            B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot2)),  //
@@ -4887,9 +5592,10 @@
       {"unallocated = 1;\nfunction f() { return unallocated++; }\nf()",
        1 * kPointerSize,
        1,
-       13,
+       14,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(StackCheck),                                            //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)),  //
            B(ToNumber),                                             //
            B(Star), R(0),                                           //
            B(Inc),                                                  //
@@ -4900,6 +5606,7 @@
        1,
        {"unallocated"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -4915,6 +5622,7 @@
   Zone zone;
 
   int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
   int first_context_slot = Context::MIN_CONTEXT_SLOTS;
 
   FeedbackVectorSpec feedback_spec(&zone);
@@ -4926,12 +5634,15 @@
 
   int object_literal_flags =
       ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"var a = 1; a += 2;",
        2 * kPointerSize,
        1,
-       14,
+       15,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Star), R(0),      //
            B(Star), R(1),      //
@@ -4944,8 +5655,9 @@
       {"var a = 1; a /= 2;",
        2 * kPointerSize,
        1,
-       14,
+       15,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Star), R(0),      //
            B(Star), R(1),      //
@@ -4958,12 +5670,14 @@
       {"var a = { val: 2 }; a.name *= 2;",
        3 * kPointerSize,
        1,
-       24,
+       27,
        {
+           B(StackCheck),                                                   //
            B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags),  //
+           B(Star), R(1),                                                   //
            B(Star), R(0),                                                   //
            B(Star), R(1),                                                   //
-           B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)),       //
+           B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot1)),       //
            B(Star), R(2),                                                   //
            B(LdaSmi8), U8(2),                                               //
            B(Mul), R(2),                                                    //
@@ -4977,14 +5691,16 @@
       {"var a = { 1: 2 }; a[1] ^= 2;",
        4 * kPointerSize,
        1,
-       27,
+       30,
        {
+           B(StackCheck),                                                   //
            B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags),  //
+           B(Star), R(1),                                                   //
            B(Star), R(0),                                                   //
            B(Star), R(1),                                                   //
            B(LdaSmi8), U8(1),                                               //
            B(Star), R(2),                                                   //
-           B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)),         //
+           B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot1)),         //
            B(Star), R(3),                                                   //
            B(LdaSmi8), U8(2),                                               //
            B(BitwiseXor), R(3),                                             //
@@ -4997,25 +5713,27 @@
       {"var a = 1; (function f() { return a; }); a |= 24;",
        2 * kPointerSize,
        1,
-       29,
+       30,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),  //
-                           U8(1),                                          //
+           /*           */ U8(1),                                          //
            B(PushContext), R(0),                                           //
+           B(StackCheck),                                                  //
            B(LdaSmi8), U8(1),                                              //
-           B(StaContextSlot), R(0), U8(first_context_slot),                //
+           B(StaContextSlot), R(context), U8(first_context_slot),          //
            B(CreateClosure), U8(0), U8(0),                                 //
-           B(LdaContextSlot), R(0), U8(first_context_slot),                //
+           B(LdaContextSlot), R(context), U8(first_context_slot),          //
            B(Star), R(1),                                                  //
            B(LdaSmi8), U8(24),                                             //
            B(BitwiseOr), R(1),                                             //
-           B(StaContextSlot), R(0), U8(first_context_slot),                //
+           B(StaContextSlot), R(context), U8(first_context_slot),          //
            B(LdaUndefined),                                                //
            B(Return),                                                      //
        },
        1,
        {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5037,13 +5755,15 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"var global = 1;\nfunction f() { return global &= 1; }\nf()",
        1 * kPointerSize,
        1,
-       13,
+       14,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(StackCheck),                                           //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)),  //
            B(Star), R(0),                                           //
            B(LdaSmi8), U8(1),                                       //
            B(BitwiseAnd), R(0),                                     //
@@ -5055,9 +5775,10 @@
       {"unallocated = 1;\nfunction f() { return unallocated += 1; }\nf()",
        1 * kPointerSize,
        1,
-       13,
+       14,
        {
-           B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)),  //
+           B(StackCheck),                                           //
+           B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)),  //
            B(Star), R(0),                                           //
            B(LdaSmi8), U8(1),                                       //
            B(Add), R(0),                                            //
@@ -5067,6 +5788,7 @@
        1,
        {"unallocated"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5082,6 +5804,7 @@
   Zone zone;
 
   int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
   int first_context_slot = Context::MIN_CONTEXT_SLOTS;
 
   FeedbackVectorSpec feedback_spec(&zone);
@@ -5090,82 +5813,96 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"function f() { return arguments; }",
        1 * kPointerSize,
        1,
-       4,
+       7,
        {
            B(CreateMappedArguments),  //
            B(Star), R(0),             //
+           B(StackCheck),             //
+           B(Ldar), R(0),             //
            B(Return),                 //
        }},
       {"function f() { return arguments[0]; }",
        2 * kPointerSize,
        1,
-       10,
+       13,
        {
            B(CreateMappedArguments),                                //
            B(Star), R(0),                                           //
+           B(StackCheck),                                           //
+           B(Ldar), R(0),                                           //
            B(Star), R(1),                                           //
            B(LdaZero),                                              //
-           B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot)),  //
+           B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot)),  //
            B(Return),                                               //
        }},
       {"function f() { 'use strict'; return arguments; }",
        1 * kPointerSize,
        1,
-       4,
+       7,
        {
            B(CreateUnmappedArguments),  //
            B(Star), R(0),               //
+           B(StackCheck),               //
+           B(Ldar), R(0),               //
            B(Return),                   //
        }},
       {"function f(a) { return arguments[0]; }",
        3 * kPointerSize,
        2,
-       22,
+       25,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),  //
-                           U8(1),                                          //
+           /*           */ U8(1),                                          //
            B(PushContext), R(1),                                           //
            B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex),           //
-           B(StaContextSlot), R(1), U8(first_context_slot),                //
+           B(StaContextSlot), R(context), U8(first_context_slot),          //
            B(CreateMappedArguments),                                       //
            B(Star), R(0),                                                  //
+           B(StackCheck),                                                  //
+           B(Ldar), R(0),                                                  //
            B(Star), R(2),                                                  //
            B(LdaZero),                                                     //
-           B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot)),         //
+           B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot)),         //
            B(Return),                                                      //
        }},
       {"function f(a, b, c) { return arguments; }",
        2 * kPointerSize,
        4,
-       26,
+       29,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),  //
-                           U8(1),                                          //
+           /*           */ U8(1),                                          //
            B(PushContext), R(1),                                           //
            B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 2),       //
-           B(StaContextSlot), R(1), U8(first_context_slot + 2),            //
+           B(StaContextSlot), R(context), U8(first_context_slot + 2),      //
            B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 1),       //
-           B(StaContextSlot), R(1), U8(first_context_slot + 1),            //
+           B(StaContextSlot), R(context), U8(first_context_slot + 1),      //
            B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex),           //
-           B(StaContextSlot), R(1), U8(first_context_slot),                //
+           B(StaContextSlot), R(context), U8(first_context_slot),          //
            B(CreateMappedArguments),                                       //
            B(Star), R(0),                                                  //
+           B(StackCheck),                                                  //
+           B(Ldar), R(0),                                                  //
            B(Return),                                                      //
        }},
       {"function f(a, b, c) { 'use strict'; return arguments; }",
        1 * kPointerSize,
        4,
-       4,
+       7,
        {
            B(CreateUnmappedArguments),  //
            B(Star), R(0),               //
+           B(StackCheck),               //
+           B(Ldar), R(0),               //
            B(Return),                   //
        }},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5174,14 +5911,119 @@
   }
 }
 
+TEST(CreateRestParameter) {
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+  Zone zone;
+
+  FeedbackVectorSpec feedback_spec(&zone);
+  FeedbackVectorSlot slot = feedback_spec.AddKeyedLoadICSlot();
+  FeedbackVectorSlot slot1 = feedback_spec.AddKeyedLoadICSlot();
+
+  Handle<i::TypeFeedbackVector> vector =
+      i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+
+  // clang-format off
+  ExpectedSnippet<int> snippets[] = {
+      {"function f(...restArgs) { return restArgs; }",
+       1 * kPointerSize,
+       1,
+       7,
+       {
+           B(CreateRestParameter),         //
+           B(Star), R(0),                  //
+           B(StackCheck),                  //
+           B(Ldar), R(0),                  //
+           B(Return),                      //
+       },
+       0,
+       {}},
+      {"function f(a, ...restArgs) { return restArgs; }",
+       2 * kPointerSize,
+       2,
+       14,
+       {
+           B(CreateRestParameter),         //
+           B(Star), R(0),                  //
+           B(LdaTheHole),                  //
+           B(Star), R(1),                  //
+           B(StackCheck),                  //
+           B(Ldar), A(1, 2),               //
+           B(Star), R(1),                  //
+           B(Ldar), R(0),                  //
+           B(Return),                      //
+       },
+       0,
+       {}},
+      {"function f(a, ...restArgs) { return restArgs[0]; }",
+       3 * kPointerSize,
+       2,
+       20,
+       {
+           B(CreateRestParameter),                                  //
+           B(Star), R(0),                                           //
+           B(LdaTheHole),                                           //
+           B(Star), R(1),                                           //
+           B(StackCheck),                                           //
+           B(Ldar), A(1, 2),                                        //
+           B(Star), R(1),                                           //
+           B(Ldar), R(0),                                           //
+           B(Star), R(2),                                           //
+           B(LdaZero),                                              //
+           B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot)),  //
+           B(Return),                                               //
+       },
+       0,
+       {}},
+      {"function f(a, ...restArgs) { return restArgs[0] + arguments[0]; }",
+       5 * kPointerSize,
+       2,
+       35,
+       {
+           B(CreateUnmappedArguments),                               //
+           B(Star), R(0),                                            //
+           B(CreateRestParameter),                                   //
+           B(Star), R(1),                                            //
+           B(LdaTheHole),                                            //
+           B(Star), R(2),                                            //
+           B(StackCheck),                                            //
+           B(Ldar), A(1, 2),                                         //
+           B(Star), R(2),                                            //
+           B(Ldar), R(1),                                            //
+           B(Star), R(3),                                            //
+           B(LdaZero),                                               //
+           B(KeyedLoadIC), R(3), U8(vector->GetIndex(slot)),   //
+           B(Star), R(4),                                            //
+           B(Ldar), R(0),                                            //
+           B(Star), R(3),                                            //
+           B(LdaZero),                                               //
+           B(KeyedLoadIC), R(3), U8(vector->GetIndex(slot1)),  //
+           B(Add), R(4),                                             //
+           B(Return),                                                //
+       },
+       0,
+       {}},
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunction(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+}
 
 TEST(IllegalRedeclaration) {
+  bool old_legacy_const_flag = FLAG_legacy_const;
+  FLAG_legacy_const = true;
+
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
   CHECK_GE(MessageTemplate::kVarRedeclaration, 128);
   // Must adapt bytecode if this changes.
 
+  // clang-format off
   ExpectedSnippet<Handle<Object>, 2> snippets[] = {
       {"const a = 1; { var a = 2; }",
        3 * kPointerSize,
@@ -5199,12 +6041,15 @@
        {helper.factory()->NewNumberFromInt(MessageTemplate::kVarRedeclaration),
         helper.factory()->NewStringFromAsciiChecked("a")}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
         helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
     CheckBytecodeArrayEqual(snippets[i], bytecode_array);
   }
+
+  FLAG_legacy_const = old_legacy_const_flag;
 }
 
 
@@ -5226,53 +6071,69 @@
   Handle<i::TypeFeedbackVector> vector =
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"for (var p in null) {}",
        2 * kPointerSize,
        1,
-       2,
-       {B(LdaUndefined), B(Return)},
+       3,
+       {
+           B(StackCheck),    //
+           B(LdaUndefined),  //
+           B(Return)         //
+       },
        0},
       {"for (var p in undefined) {}",
        2 * kPointerSize,
        1,
-       2,
-       {B(LdaUndefined), B(Return)},
+       3,
+       {
+           B(StackCheck),    //
+           B(LdaUndefined),  //
+           B(Return)         //
+       },
        0},
       {"for (var p in undefined) {}",
        2 * kPointerSize,
        1,
-       2,
-       {B(LdaUndefined), B(Return)},
+       3,
+       {
+           B(StackCheck),    //
+           B(LdaUndefined),  //
+           B(Return)         //
+       },
        0},
       {"var x = 'potatoes';\n"
        "for (var p in x) { return p; }",
        8 * kPointerSize,
        1,
-       45,
+       46,
        {
-           B(LdaConstant), U8(0),                 //
-           B(Star), R(1),                         //
-           B(JumpIfUndefined), U8(39),            //
-           B(JumpIfNull), U8(37),                 //
-           B(ToObject),                           //
-           B(JumpIfNull), U8(34),                 //
-           B(Star), R(3),                         //
-           B(ForInPrepare), R(4), R(5), R(6),     //
-           B(LdaZero),                            //
-           B(Star), R(7),                         //
-           B(ForInDone), R(7), R(6),              //
-           B(JumpIfTrue), U8(20),                 //
-           B(ForInNext), R(3), R(4), R(5), R(7),  //
-           B(JumpIfUndefined), U8(7),             //
-           B(Star), R(0),                         //
-           B(Star), R(2),                         //
-           B(Return),                             //
-           B(ForInStep), R(7),                    //
-           B(Star), R(7),                         //
-           B(Jump), U8(-21),                      //
-           B(LdaUndefined),                       //
-           B(Return),                             //
+           B(StackCheck),                   //
+           B(LdaConstant), U8(0),           //
+           B(Star), R(1),                   //
+           B(JumpIfUndefined), U8(39),      //
+           B(JumpIfNull), U8(37),           //
+           B(ToObject),                     //
+           B(JumpIfNull), U8(34),           //
+           B(Star), R(3),                   //
+           B(ForInPrepare), R(4),           //
+           B(LdaZero),                      //
+           B(Star), R(7),                   //
+           B(ForInDone), R(7), R(6),        //
+           B(JumpIfTrue), U8(22),           //
+           B(ForInNext), R(3), R(7), R(4),  //
+           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(-23),                //
+           B(LdaUndefined),                 //
+           B(Return),                       //
        },
        1,
        {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
@@ -5280,8 +6141,9 @@
        "for (var p in [1,2,3]) { x += p; }",
        9 * kPointerSize,
        1,
-       57,
+       58,
        {
+           B(StackCheck),                               //
            B(LdaZero),                                  //
            B(Star), R(1),                               //
            B(CreateArrayLiteral), U8(0), U8(0), U8(3),  //
@@ -5290,14 +6152,16 @@
            B(ToObject),                                 //
            B(JumpIfNull), U8(43),                       //
            B(Star), R(3),                               //
-           B(ForInPrepare), R(4), R(5), R(6),           //
+           B(ForInPrepare), R(4),                       //
            B(LdaZero),                                  //
            B(Star), R(7),                               //
            B(ForInDone), R(7), R(6),                    //
-           B(JumpIfTrue), U8(29),                       //
-           B(ForInNext), R(3), R(4), R(5), R(7),        //
-           B(JumpIfUndefined), U8(16),                  //
+           B(JumpIfTrue), U8(31),                       //
+           B(ForInNext), R(3), R(7), R(4),              //
+           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),                               //
@@ -5306,7 +6170,7 @@
            B(Star), R(1),                               //
            B(ForInStep), R(7),                          //
            B(Star), R(7),                               //
-           B(Jump), U8(-30),                            //
+           B(Jump), U8(-32),                            //
            B(LdaUndefined),                             //
            B(Return),                                   //
        },
@@ -5319,31 +6183,34 @@
        "}",
        8 * kPointerSize,
        1,
-       94,
+       95,
        {
+           B(StackCheck),                                                  //
            B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
+           B(Star), R(1),                                                  //
            B(Star), R(0),                                                  //
            B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags),          //
-           B(JumpIfUndefined), U8(82),                                     //
-           B(JumpIfNull), U8(80),                                          //
+           B(JumpIfUndefined), U8(80),                                     //
+           B(JumpIfNull), U8(78),                                          //
            B(ToObject),                                                    //
-           B(JumpIfNull), U8(77),                                          //
+           B(JumpIfNull), U8(75),                                          //
            B(Star), R(1),                                                  //
-           B(ForInPrepare), R(2), R(3), R(4),                              //
+           B(ForInPrepare), R(2),                                          //
            B(LdaZero),                                                     //
            B(Star), R(5),                                                  //
            B(ForInDone), R(5), R(4),                                       //
            B(JumpIfTrue), U8(63),                                          //
-           B(ForInNext), R(1), R(2), R(3), R(5),                           //
-           B(JumpIfUndefined), U8(50),                                     //
+           B(ForInNext), R(1), R(5), R(2),                                 //
+           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(vector->GetIndex(slot4)),     //
+           B(StackCheck),                                                  //
            B(Ldar), R(0),                                                  //
            B(Star), R(6),                                                  //
-           B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot2)),      //
+           B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot2)),      //
            B(Star), R(7),                                                  //
            B(LdaSmi8), U8(10),                                             //
            B(TestEqual), R(7),                                             //
@@ -5351,7 +6218,7 @@
            B(Jump), U8(20),                                                //
            B(Ldar), R(0),                                                  //
            B(Star), R(6),                                                  //
-           B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot3)),      //
+           B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot3)),      //
            B(Star), R(7),                                                  //
            B(LdaSmi8), U8(20),                                             //
            B(TestEqual), R(7),                                             //
@@ -5370,23 +6237,24 @@
        "for (x[0] in [1,2,3]) { return x[3]; }",
        9 * kPointerSize,
        1,
-       71,
+       70,
        {
+           B(StackCheck),                                                   //
            B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags),           //
            B(Star), R(0),                                                   //
            B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags),           //
-           B(JumpIfUndefined), U8(59),                                      //
-           B(JumpIfNull), U8(57),                                           //
+           B(JumpIfUndefined), U8(57),                                      //
+           B(JumpIfNull), U8(55),                                           //
            B(ToObject),                                                     //
-           B(JumpIfNull), U8(54),                                           //
+           B(JumpIfNull), U8(52),                                           //
            B(Star), R(1),                                                   //
-           B(ForInPrepare), R(2), R(3), R(4),                               //
+           B(ForInPrepare), R(2),                                           //
            B(LdaZero),                                                      //
            B(Star), R(5),                                                   //
            B(ForInDone), R(5), R(4),                                        //
            B(JumpIfTrue), U8(40),                                           //
-           B(ForInNext), R(1), R(2), R(3), R(5),                            //
-           B(JumpIfUndefined), U8(27),                                      //
+           B(ForInNext), R(1), R(5), R(2),                                  //
+           B(JumpIfUndefined), U8(28),                                      //
            B(Star), R(6),                                                   //
            B(Ldar), R(0),                                                   //
            B(Star), R(7),                                                   //
@@ -5394,10 +6262,11 @@
            B(Star), R(8),                                                   //
            B(Ldar), R(6),                                                   //
            B(KeyedStoreICSloppy), R(7), R(8), U8(vector->GetIndex(slot3)),  //
+           B(StackCheck),                                                   //
            B(Ldar), R(0),                                                   //
            B(Star), R(6),                                                   //
            B(LdaSmi8), U8(3),                                               //
-           B(KeyedLoadICSloppy), R(6), U8(vector->GetIndex(slot2)),         //
+           B(KeyedLoadIC), R(6), U8(vector->GetIndex(slot2)),         //
            B(Return),                                                       //
            B(ForInStep), R(5),                                              //
            B(Star), R(5),                                                   //
@@ -5408,6 +6277,259 @@
        2,
        {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE}},
   };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+}
+
+
+// TODO(rmcilroy): Do something about this; new bytecode is too large
+// (150+ instructions) to adapt manually.
+DISABLED_TEST(ForOf) {
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+  Zone zone;
+
+  int array_literal_flags =
+      ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
+  int object_literal_flags =
+      ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+
+  FeedbackVectorSpec feedback_spec(&zone);
+  FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot();
+  FeedbackVectorSlot slot2 = feedback_spec.AddKeyedLoadICSlot();
+  FeedbackVectorSlot slot3 = feedback_spec.AddCallICSlot();
+  FeedbackVectorSlot slot4 = feedback_spec.AddLoadICSlot();
+  FeedbackVectorSlot slot5 = feedback_spec.AddLoadICSlot();
+  FeedbackVectorSlot slot6 = feedback_spec.AddLoadICSlot();
+  FeedbackVectorSlot slot7 = feedback_spec.AddStoreICSlot();
+  FeedbackVectorSlot slot8 = feedback_spec.AddLoadICSlot();
+  Handle<i::TypeFeedbackVector> vector =
+      i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+
+  // clang-format off
+  ExpectedSnippet<InstanceType, 8> snippets[] = {
+      {"for (var p of [0, 1, 2]) {}",
+       7 * kPointerSize,
+       1,
+       86,
+       {
+           B(StackCheck),                                                   //
+           B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags),    //
+           B(Star), R(5),                                                   //
+           B(LdaConstant), U8(1),                                           //
+           B(KeyedLoadIC), R(5), U8(vector->GetIndex(slot2)),         //
+           B(Star), R(4),                                                   //
+           B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)),         //
+           B(Star), R(1),                                                   //
+           B(Ldar), R(1),                                                   //
+           B(Star), R(6),                                                   //
+           B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot4)),       //
+           B(Star), R(5),                                                   //
+           B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)),         //
+           B(Star), R(2),                                                   //
+           B(Star), R(4),                                                   //
+           B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(4), U8(1),  //
+           B(LogicalNot),                                                   //
+           B(JumpIfFalse), U8(11),                                          //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(4),                                                   //
+           B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject),   //
+           /*           */ R(4), U8(1),                                     //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(4),                                                   //
+           B(LoadIC), R(4), U8(3), U8(vector->GetIndex(slot5)),       //
+           B(JumpIfToBooleanTrue), U8(19),                                  //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(4),                                                   //
+           B(LoadIC), R(4), U8(4), U8(vector->GetIndex(slot6)),       //
+           B(Star), R(0),                                                   //
+           B(StackCheck),                                                   //
+           B(Ldar), R(0),                                                   //
+           B(Star), R(3),                                                   //
+           B(Jump), U8(-61),                                                //
+           B(LdaUndefined),                                                 //
+           B(Return),                                                       //
+       },
+       5,
+       {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SYMBOL_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+      {"var x = 'potatoes';\n"
+       "for (var p of x) { return p; }",
+       8 * kPointerSize,
+       1,
+       85,
+       {
+           B(StackCheck),                                                   //
+           B(LdaConstant), U8(0),                                           //
+           B(Star), R(3),                                                   //
+           B(Star), R(6),                                                   //
+           B(LdaConstant), U8(1),                                           //
+           B(KeyedLoadIC), R(6), U8(vector->GetIndex(slot2)),         //
+           B(Star), R(5),                                                   //
+           B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot1)),         //
+           B(Star), R(1),                                                   //
+           B(Ldar), R(1),                                                   //
+           B(Star), R(7),                                                   //
+           B(LoadIC), R(7), U8(2), U8(vector->GetIndex(slot4)),       //
+           B(Star), R(6),                                                   //
+           B(Call), R(6), R(7), U8(1), U8(vector->GetIndex(slot3)),         //
+           B(Star), R(2),                                                   //
+           B(Star), R(5),                                                   //
+           B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(5), U8(1),  //
+           B(LogicalNot),                                                   //
+           B(JumpIfFalse), U8(11),                                          //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(5),                                                   //
+           B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject),   //
+           /*           */ R(5), U8(1),                                     //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(5),                                                   //
+           B(LoadIC), R(5), U8(3), U8(vector->GetIndex(slot5)),       //
+           B(JumpIfToBooleanTrue), U8(18),                                  //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(5),                                                   //
+           B(LoadIC), R(5), U8(4), U8(vector->GetIndex(slot6)),       //
+           B(Star), R(0),                                                   //
+           B(StackCheck),                                                   //
+           B(Ldar), R(0),                                                   //
+           B(Star), R(4),                                                   //
+           B(Return),                                                       //
+           B(LdaUndefined),                                                 //
+           B(Return),                                                       //
+       },
+       5,
+       {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::SYMBOL_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+      {"for (var x of [10, 20, 30]) {\n"
+       "  if (x == 10) continue;\n"
+       "  if (x == 20) break;\n"
+       "}",
+       7 * kPointerSize,
+       1,
+       108,
+       {
+           B(StackCheck),                                                   //
+           B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags),    //
+           B(Star), R(5),                                                   //
+           B(LdaConstant), U8(1),                                           //
+           B(KeyedLoadIC), R(5), U8(vector->GetIndex(slot2)),         //
+           B(Star), R(4),                                                   //
+           B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)),         //
+           B(Star), R(1),                                                   //
+           B(Ldar), R(1),                                                   //
+           B(Star), R(6),                                                   //
+           B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot4)),       //
+           B(Star), R(5),                                                   //
+           B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)),         //
+           B(Star), R(2),                                                   //
+           B(Star), R(4),                                                   //
+           B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(4), U8(1),  //
+           B(LogicalNot),                                                   //
+           B(JumpIfFalse), U8(11),                                          //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(4),                                                   //
+           B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject),   //
+           /*           */ R(4), U8(1),                                     //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(4),                                                   //
+           B(LoadIC), R(4), U8(3), U8(vector->GetIndex(slot5)),       //
+           B(JumpIfToBooleanTrue), U8(41),                                  //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(4),                                                   //
+           B(LoadIC), R(4), U8(4), U8(vector->GetIndex(slot6)),       //
+           B(Star), R(0),                                                   //
+           B(StackCheck),                                                   //
+           B(Ldar), R(0),                                                   //
+           B(Star), R(3),                                                   //
+           B(Star), R(4),                                                   //
+           B(LdaSmi8), U8(10),                                              //
+           B(TestEqual), R(4),                                              //
+           B(JumpIfFalse), U8(4),                                           //
+           B(Jump), U8(-69),                                                //
+           B(Ldar), R(3),                                                   //
+           B(Star), R(4),                                                   //
+           B(LdaSmi8), U8(20),                                              //
+           B(TestEqual), R(4),                                              //
+           B(JumpIfFalse), U8(4),                                           //
+           B(Jump), U8(4),                                                  //
+           B(Jump), U8(-83),                                                //
+           B(LdaUndefined),                                                 //
+           B(Return),                                                       //
+       },
+       5,
+       {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SYMBOL_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+      {"var x = { 'a': 1, 'b': 2 };\n"
+       "for (x['a'] of [1,2,3]) { return x['a']; }",
+       6 * kPointerSize,
+       1,
+       103,
+       {
+           B(StackCheck),                                                   //
+           B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags),  //
+           B(Star), R(3),                                                   //
+           B(Star), R(2),                                                   //
+           B(CreateArrayLiteral), U8(1), U8(1), U8(array_literal_flags),    //
+           B(Star), R(4),                                                   //
+           B(LdaConstant), U8(2),                                           //
+           B(KeyedLoadIC), R(4), U8(vector->GetIndex(slot2)),         //
+           B(Star), R(3),                                                   //
+           B(Call), R(3), R(4), U8(1), U8(vector->GetIndex(slot1)),         //
+           B(Star), R(0),                                                   //
+           B(Ldar), R(0),                                                   //
+           B(Star), R(5),                                                   //
+           B(LoadIC), R(5), U8(3), U8(vector->GetIndex(slot4)),       //
+           B(Star), R(4),                                                   //
+           B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot3)),         //
+           B(Star), R(1),                                                   //
+           B(Star), R(3),                                                   //
+           B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(3), U8(1),  //
+           B(LogicalNot),                                                   //
+           B(JumpIfFalse), U8(11),                                          //
+           B(Ldar), R(1),                                                   //
+           B(Star), R(3),                                                   //
+           B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject),   //
+           /*           */ R(3), U8(1),                                     //
+           B(Ldar), R(1),                                                   //
+           B(Star), R(3),                                                   //
+           B(LoadIC), R(3), U8(4), U8(vector->GetIndex(slot5)),       //
+           B(JumpIfToBooleanTrue), U8(28),                                  //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(3),                                                   //
+           B(Ldar), R(1),                                                   //
+           B(Star), R(4),                                                   //
+           B(LoadIC), R(4), U8(5), U8(vector->GetIndex(slot6)),       //
+           B(StoreICSloppy), R(3), U8(6), U8(vector->GetIndex(slot7)),      //
+           B(StackCheck),                   //
+           B(Ldar), R(2),                                                   //
+           B(Star), R(3),                                                   //
+           B(LoadIC), R(3), U8(6), U8(vector->GetIndex(slot8)),       //
+           B(Return),                                                       //
+           B(LdaUndefined),                                                 //
+           B(Return),                                                       //
+       },
+       7,
+       {InstanceType::FIXED_ARRAY_TYPE,
+        InstanceType::FIXED_ARRAY_TYPE,
+        InstanceType::SYMBOL_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5421,12 +6543,14 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"return 1 ? 2 : 3;",
        0,
        1,
-       11,
+       12,
        {
+           B(StackCheck),                   //
            B(LdaSmi8), U8(1),               //
            B(JumpIfToBooleanFalse), U8(6),  //
            B(LdaSmi8), U8(2),               //
@@ -5437,8 +6561,9 @@
       {"return 1 ? 2 ? 3 : 4 : 5;",
        0,
        1,
-       19,
+       20,
        {
+           B(StackCheck),                    //
            B(LdaSmi8), U8(1),                //
            B(JumpIfToBooleanFalse), U8(14),  //
            B(LdaSmi8), U8(2),                //
@@ -5451,6 +6576,7 @@
            B(Return),                        //
        }},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5464,6 +6590,7 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"var a = 1;\n"
        "switch(a) {\n"
@@ -5472,8 +6599,9 @@
        "}\n",
        3 * kPointerSize,
        1,
-       30,
+       31,
        {
+           B(StackCheck),             //
            B(LdaSmi8), U8(1),         //
            B(Star), R(1),             // The tag variable is allocated as a
            B(Star), R(0),             // local by the parser, hence the store
@@ -5499,8 +6627,9 @@
        "}\n",
        3 * kPointerSize,
        1,
-       36,
+       37,
        {
+           B(StackCheck),             //
            B(LdaSmi8), U8(1),         //
            B(Star), R(1),             //
            B(Star), R(0),             //
@@ -5528,8 +6657,9 @@
        "}\n",
        3 * kPointerSize,
        1,
-       34,
+       35,
        {
+           B(StackCheck),             //
            B(LdaSmi8), U8(1),         //
            B(Star), R(1),             //
            B(Star), R(0),             //
@@ -5557,8 +6687,9 @@
        "}\n",
        3 * kPointerSize,
        1,
-       34,
+       35,
        {
+           B(StackCheck),             //
            B(LdaSmi8), U8(1),         //
            B(Star), R(1),             //
            B(Star), R(0),             //
@@ -5586,8 +6717,9 @@
        "}\n",
        3 * kPointerSize,
        1,
-       43,
+       44,
        {
+           B(StackCheck),             //
            B(LdaSmi8), U8(1),         //
            B(Star), R(1),             //
            B(TypeOf),                 //
@@ -5619,8 +6751,9 @@
        "}\n",
        3 * kPointerSize,
        1,
-       31,
+       32,
        {
+           B(StackCheck),             //
            B(LdaSmi8), U8(1),         //
            B(Star), R(1),             //
            B(Star), R(0),             //
@@ -5647,8 +6780,9 @@
        "}\n",
        3 * kPointerSize,
        1,
-       288,
+       289,
        {
+           B(StackCheck),                 //
            B(LdaSmi8), U8(1),             //
            B(Star), R(1),                 //
            B(Star), R(0),                 //
@@ -5683,8 +6817,9 @@
        "}\n",
        5 * kPointerSize,
        1,
-       60,
+       61,
        {
+           B(StackCheck),             //
            B(LdaSmi8), U8(1),         //
            B(Star), R(2),             //
            B(Star), R(0),             //
@@ -5718,6 +6853,7 @@
            B(Return),                 //
        }},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5733,12 +6869,14 @@
 
   // Check that we generate JumpIfToBoolean if they are at the start of basic
   // blocks.
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"var a = 1; if (a || a < 0) { return 1; }",
        2 * kPointerSize,
        1,
-       20,
+       21,
        {
+           B(StackCheck),                   //
            B(LdaSmi8), U8(1),               //
            B(Star), R(0),                   //
            B(JumpIfToBooleanTrue), U8(9),   //
@@ -5755,8 +6893,9 @@
       {"var a = 1; if (a && a < 0) { return 1; }",
        2 * kPointerSize,
        1,
-       20,
+       21,
        {
+           B(StackCheck),                   //
            B(LdaSmi8), U8(1),               //
            B(Star), R(0),                   //
            B(JumpIfToBooleanFalse), U8(9),  //
@@ -5773,8 +6912,9 @@
       {"var a = 1; a = (a || a < 0) ? 2 : 3;",
        2 * kPointerSize,
        1,
-       25,
+       26,
        {
+           B(StackCheck),                   //
            B(LdaSmi8), U8(1),               //
            B(Star), R(0),                   //
            B(JumpIfToBooleanTrue), U8(9),   //
@@ -5791,6 +6931,7 @@
            B(Return),                       //
        }},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5804,20 +6945,23 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"return; var a = 1; a();",
        1 * kPointerSize,
        1,
-       2,
+       3,
        {
+           B(StackCheck),    //
            B(LdaUndefined),  //
            B(Return),        //
        }},
       {"if (false) { return; }; var a = 1;",
        1 * kPointerSize,
        1,
-       6,
+       7,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Star), R(0),      //
            B(LdaUndefined),    //
@@ -5826,16 +6970,18 @@
       {"if (true) { return 1; } else { return 2; };",
        0,
        1,
-       3,
+       4,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Return),          //
        }},
       {"var a = 1; if (a) { return 1; }; return 2;",
        1 * kPointerSize,
        1,
-       12,
+       13,
        {
+           B(StackCheck),                   //
            B(LdaSmi8), U8(1),               //
            B(Star), R(0),                   //
            B(JumpIfToBooleanFalse), U8(5),  //
@@ -5845,6 +6991,7 @@
            B(Return),                       //
        }},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5860,31 +7007,46 @@
 
   int closure = Register::function_closure().index();
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"var f;\n f = function f() { }",
-       1 * kPointerSize,
+       2 * kPointerSize,
        1,
-       9,
+       19,
        {
-           B(LdaTheHole),        //
-           B(Star), R(0),        //
-           B(Ldar), R(closure),  //
-           B(Star), R(0),        //
-           B(LdaUndefined),      //
-           B(Return),            //
+           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),                //
        }},
       {"var f;\n f = function f() { return f; }",
-       1 * kPointerSize,
+       2 * kPointerSize,
        1,
-       8,
+       23,
        {
-           B(LdaTheHole),        //
-           B(Star), R(0),        //
-           B(Ldar), R(closure),  //
-           B(Star), R(0),        //
-           B(Return),            //
+           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),                //
        }},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5900,27 +7062,44 @@
 
   int new_target = Register::new_target().index();
 
-  ExpectedSnippet<int> snippets[] = {
+  // clang-format off
+  ExpectedSnippet<InstanceType> snippets[] = {
       {"return new.target;",
-       1 * kPointerSize,
+       2 * kPointerSize,
        1,
-       5,
+       19,
        {
-           B(Ldar), R(new_target),  //
-           B(Star), R(0),           //
-           B(Return),               //
-       }},
+           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),                                                        //
+       },
+       1,
+       {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
       {"new.target;",
-       1 * kPointerSize,
+       2 * kPointerSize,
        1,
-       6,
+       20,
        {
-           B(Ldar), R(new_target),  //
-           B(Star), R(0),           //
-           B(LdaUndefined),         //
-           B(Return),               //
-       }},
-  };
+           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),                                                        //
+       },
+       1,
+       {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}};
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -5934,6 +7113,7 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<int> snippets[] = {
       {"var ld_a = 1;\n"          // This test is to check Ldar does not
        "while(true) {\n"          // get removed if the preceding Star is
@@ -5943,9 +7123,11 @@
        "return ld_a;",
        2 * kPointerSize,
        1,
-       29,
-       {B(LdaSmi8), U8(1),         //
+       31,
+       {B(StackCheck),             //
+        B(LdaSmi8), U8(1),         //
         B(Star), R(0),             //
+        B(StackCheck),             //
         B(Ldar), R(0),             //  This load should not be removed as it
         B(Star), R(1),             //  is the target of the branch.
         B(Ldar), R(0),             //
@@ -5956,7 +7138,7 @@
         B(TestGreaterThan), R(1),  //
         B(JumpIfFalse), U8(4),     //
         B(Jump), U8(4),            //
-        B(Jump), U8(-20),          //
+        B(Jump), U8(-21),          //
         B(Ldar), R(0),             //
         B(Return)}},
       {"var ld_a = 1;\n"
@@ -5967,9 +7149,11 @@
        "return ld_a;",
        2 * kPointerSize,
        1,
-       27,
-       {B(LdaSmi8), U8(1),         //
+       29,
+       {B(StackCheck),             //
+        B(LdaSmi8), U8(1),         //
         B(Star), R(0),             //
+        B(StackCheck),             //
         B(Ldar), R(0),             //
         B(Star), R(1),             //
         B(Ldar), R(0),             //
@@ -5987,8 +7171,9 @@
        "  return ld_a;",
        2 * kPointerSize,
        1,
-       13,
+       14,
        {
+           B(StackCheck),      //
            B(LdaSmi8), U8(1),  //
            B(Star), R(0),      //
            B(Star), R(1),      //
@@ -5998,6 +7183,7 @@
            B(Return)           //
        }},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -6011,13 +7197,15 @@
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"var x = 0, y = 1;\n"
        "return (x = 2, y = 3, x = 4, y = 5)",
        2 * kPointerSize,
        1,
-       24,
+       25,
        {
+           B(StackCheck),              //
            B(LdaZero), B(Star), R(0),  //
            B(LdaSmi8), U8(1),          //
            B(Star), R(1),              //
@@ -6037,8 +7225,9 @@
        "return y",
        2 * kPointerSize,
        1,
-       11,
+       12,
        {
+           B(StackCheck),        //
            B(LdaSmi8), U8(55),   //
            B(Star), R(0),        //
            B(LdaSmi8), U8(100),  //
@@ -6052,8 +7241,9 @@
        "return x;",
        3 * kPointerSize,
        1,
-       23,
+       24,
        {
+           B(StackCheck),        //
            B(LdaSmi8), U8(55),   //
            B(Star), R(0),        //
            B(Star), R(1),        //
@@ -6074,8 +7264,9 @@
        "return x;",
        3 * kPointerSize,
        1,
-       31,
+       32,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(55),  //
            B(Star), R(0),       //
            B(LdaSmi8), U8(56),  //
@@ -6100,8 +7291,9 @@
        "return y;",
        4 * kPointerSize,
        1,
-       31,
+       32,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(55),  //
            B(Star), R(0),       //
            B(Star), R(2),       //
@@ -6125,8 +7317,9 @@
        "return x;",
        3 * kPointerSize,
        1,
-       31,
+       32,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(55),  //
            B(Star), R(0),       //
            B(Star), R(1),       //
@@ -6150,8 +7343,9 @@
        "y;\n",
        5 * kPointerSize,
        1,
-       69,
+       70,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(10),  //
            B(Star), R(0),       //
            B(LdaSmi8), U8(20),  //
@@ -6193,8 +7387,9 @@
        "return 1 + x + (x++) + (++x);\n",
        4 * kPointerSize,
        1,
-       37,
+       38,
        {
+           B(StackCheck),       //
            B(LdaSmi8), U8(17),  //
            B(Star), R(0),       //
            B(LdaSmi8), U8(1),   //
@@ -6217,7 +7412,9 @@
            B(Add), R(3),        //
            B(Return),           //
        },
-       0}};
+       0}
+  };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -6233,49 +7430,51 @@
   Zone zone;
 
   int closure = Register::function_closure().index();
-  int context = Register::function_context().index();
+  int context = Register::current_context().index();
   int new_target = Register::new_target().index();
 
   int first_context_slot = Context::MIN_CONTEXT_SLOTS;
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"return eval('1;');",
        9 * kPointerSize,
        1,
-       67,
+       65,
        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),     //
-                           U8(1),                                             //
-           B(PushContext), R(0),                                              //
-           B(Ldar), THIS(1),                                                  //
-           B(StaContextSlot), R(0), U8(first_context_slot),                   //
-           B(CreateMappedArguments),                                          //
-           B(StaContextSlot), R(0), U8(first_context_slot + 1),               //
-           B(Ldar), R(new_target),                                            //
-           B(StaContextSlot), R(0), U8(first_context_slot + 2),               //
-           B(Mov), R(context), R(3),                                          //
-           B(LdaConstant), U8(0),                                             //
-           B(Star), R(4),                                                     //
-           B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot),              //
-                                  R(3), U8(2), 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(LdaSmi8), U8(10),                                                //
-           B(Star), R(8),                                                     //
-           B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4),    //
-                           U8(5),                                             //
-           B(Star), R(1),                                                     //
-           B(Call), R(1), R(2), U8(1), U8(0),                                 //
-           B(Return),                                                         //
+           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),   //
+           /*           */ U8(1),                                           //
+           B(PushContext), R(0),                                            //
+           B(Ldar), THIS(1),                                                //
+           B(StaContextSlot), R(context), U8(first_context_slot),           //
+           B(CreateMappedArguments),                                        //
+           B(StaContextSlot), R(context), U8(first_context_slot + 1),       //
+           B(Ldar), R(new_target),                                          //
+           B(StaContextSlot), R(context), U8(first_context_slot + 2),       //
+           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(LdaSmi8), U8(10),                                              //
+           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),                                                       //
        },
        2,
        {"eval", "1;"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -6290,125 +7489,127 @@
   BytecodeGeneratorHelper helper;
 
   int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
   int first_context_slot = Context::MIN_CONTEXT_SLOTS;
-  int context = Register::function_context().index();
   int new_target = Register::new_target().index();
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"eval('var x = 10;'); return x;",
        9 * kPointerSize,
        1,
-       69,
+       67,
        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),     //
-                           U8(1),                                             //
-           B(PushContext), R(0),                                              //
-           B(Ldar), THIS(1),                                                  //
-           B(StaContextSlot), R(0), U8(first_context_slot),                   //
-           B(CreateMappedArguments),                                          //
-           B(StaContextSlot), R(0), U8(first_context_slot + 1),               //
-           B(Ldar), R(new_target),                                            //
-           B(StaContextSlot), R(0), U8(first_context_slot + 2),               //
-           B(Mov), R(context), R(3),                                          //
-           B(LdaConstant), U8(0),                                             //
-           B(Star), R(4),                                                     //
-           B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot),              //
-                                  R(3), U8(2), 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(LdaSmi8), U8(10),                                                //
-           B(Star), R(8),                                                     //
-           B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4),    //
-                           U8(5),                                             //
-           B(Star), R(1),                                                     //
-           B(Call), R(1), R(2), U8(1), U8(0),                                 //
-           B(LdaLookupSlot), U8(2),                                           //
-           B(Return),                                                         //
+           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),   //
+           /*           */ U8(1),                                           //
+           B(PushContext), R(0),                                            //
+           B(Ldar), THIS(1),                                                //
+           B(StaContextSlot), R(context), U8(first_context_slot),           //
+           B(CreateMappedArguments),                                        //
+           B(StaContextSlot), R(context), U8(first_context_slot + 1),       //
+           B(Ldar), R(new_target),                                          //
+           B(StaContextSlot), R(context), U8(first_context_slot + 2),       //
+           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(LdaSmi8), U8(10),                                              //
+           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),                                                       //
        },
        3,
        {"eval", "var x = 10;", "x"}},
       {"eval('var x = 10;'); return typeof x;",
-        9 * kPointerSize,
-        1,
-        70,
-        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),     //
-                           U8(1),                                             //
-           B(PushContext), R(0),                                              //
-           B(Ldar), THIS(1),                                                  //
-           B(StaContextSlot), R(0), U8(first_context_slot),                   //
-           B(CreateMappedArguments),                                          //
-           B(StaContextSlot), R(0), U8(first_context_slot + 1),               //
-           B(Ldar), R(new_target),                                            //
-           B(StaContextSlot), R(0), U8(first_context_slot + 2),               //
-           B(Mov), R(context), R(3),                                          //
-           B(LdaConstant), U8(0),                                             //
-           B(Star), R(4),                                                     //
-           B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot),              //
-                                  R(3), U8(2), 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(LdaSmi8), U8(10),                                                //
-           B(Star), R(8),                                                     //
-           B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4),    //
-                           U8(5),                                             //
-           B(Star), R(1),                                                     //
-           B(Call), R(1), R(2), U8(1), U8(0),                                 //
-           B(LdaLookupSlotInsideTypeof), U8(2),                               //
-           B(TypeOf),                                                         //
-           B(Return),                                                         //
+       9 * kPointerSize,
+       1,
+       68,
+       {
+           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),   //
+           /*           */ U8(1),                                           //
+           B(PushContext), R(0),                                            //
+           B(Ldar), THIS(1),                                                //
+           B(StaContextSlot), R(context), U8(first_context_slot),           //
+           B(CreateMappedArguments),                                        //
+           B(StaContextSlot), R(context), U8(first_context_slot + 1),       //
+           B(Ldar), R(new_target),                                          //
+           B(StaContextSlot), R(context), U8(first_context_slot + 2),       //
+           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(LdaSmi8), U8(10),                                              //
+           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),                                                       //
        },
        3,
        {"eval", "var x = 10;", "x"}},
       {"x = 20; return eval('');",
        9 * kPointerSize,
        1,
-       71,
+       69,
        {
-           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),     //
-                           U8(1),                                             //
-           B(PushContext), R(0),                                              //
-           B(Ldar), THIS(1),                                                  //
-           B(StaContextSlot), R(0), U8(first_context_slot),                   //
-           B(CreateMappedArguments),                                          //
-           B(StaContextSlot), R(0), U8(first_context_slot + 1),               //
-           B(Ldar), R(new_target),                                            //
-           B(StaContextSlot), R(0), U8(first_context_slot + 2),               //
-           B(LdaSmi8), U8(20),                                                //
-           B(StaLookupSlotSloppy), U8(0),                                     //
-           B(Mov), R(context), R(3),                                          //
-           B(LdaConstant), U8(1),                                             //
-           B(Star), R(4),                                                     //
-           B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot),              //
-                                  R(3), U8(2), 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(LdaSmi8), U8(10),                                                //
-           B(Star), R(8),                                                     //
-           B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4),    //
-                           U8(5),                                             //
-           B(Star), R(1),                                                     //
-           B(Call), R(1), R(2), U8(1), U8(0),                                 //
-           B(Return),                                                         //
+           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),   //
+                           U8(1),                                           //
+           B(PushContext), R(0),                                            //
+           B(Ldar), THIS(1),                                                //
+           B(StaContextSlot), R(context), U8(first_context_slot),           //
+           B(CreateMappedArguments),                                        //
+           B(StaContextSlot), R(context), U8(first_context_slot + 1),       //
+           B(Ldar), R(new_target),                                          //
+           B(StaContextSlot), R(context), U8(first_context_slot + 2),       //
+           B(StackCheck),                                                   //
+           B(LdaSmi8), 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(LdaSmi8), U8(10),                                              //
+           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),                                                       //
        },
        3,
        {"x", "eval", ""}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -6432,31 +7633,32 @@
       i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
 
   int closure = Register::function_closure().index();
-  int context = Register::function_context().index();
+  int context = Register::current_context().index();
   int new_target = Register::new_target().index();
 
+  // clang-format off
   ExpectedSnippet<InstanceType> snippets[] = {
       {"g = function(){}; eval(''); return g();",
        9 * kPointerSize,
        1,
-       90,
+       85,
        {
            B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),   //
-                           U8(1),                                           //
+           /*           */ U8(1),                                           //
            B(PushContext), R(0),                                            //
            B(Ldar), THIS(1),                                                //
-           B(StaContextSlot), R(0), U8(4),                                  //
+           B(StaContextSlot), R(context), U8(4),                            //
            B(CreateMappedArguments),                                        //
-           B(StaContextSlot), R(0), U8(5),                                  //
+           B(StaContextSlot), R(context), U8(5),                            //
            B(Ldar), R(new_target),                                          //
-           B(StaContextSlot), R(0), U8(6),                                  //
+           B(StaContextSlot), R(context), U8(6),                            //
+           B(StackCheck),                                                   //
            B(CreateClosure), U8(0), U8(0),                                  //
            B(StaLookupSlotSloppy), U8(1),                                   //
-           B(Mov), R(context), R(3),                                        //
            B(LdaConstant), U8(2),                                           //
-           B(Star), R(4),                                                   //
-           B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot),            //
-                                  R(3), U8(2), R(1),                        //
+           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),                                              //
@@ -6469,13 +7671,12 @@
            B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4),  //
                            U8(5),                                           //
            B(Star), R(1),                                                   //
-           B(Call), R(1), R(2), U8(1), U8(0),                               //
-           B(Mov), R(context), R(3),                                        //
+           B(Call), R(1), R(2), U8(2), U8(0),                               //
            B(LdaConstant), U8(1),                                           //
-           B(Star), R(4),                                                   //
-           B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot),            //
-                                  R(3), U8(2), R(1),                        //
-           B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot2)),         //
+           B(Star), R(3),                                                   //
+           B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall),     //
+                                  R(3), U8(1), R(1),                        //
+           B(Call), R(1), R(2), U8(1), U8(vector->GetIndex(slot2)),         //
            B(Return),                                                       //
        },
        4,
@@ -6484,6 +7685,7 @@
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     Handle<BytecodeArray> bytecode_array =
@@ -6493,6 +7695,8 @@
 }
 
 
+// TODO(mythria): tests for variable/function declaration in lookup slots.
+
 TEST(LookupSlotInEval) {
   InitializedHandleScope handle_scope;
   BytecodeGeneratorHelper helper;
@@ -6505,12 +7709,14 @@
                                   "}"
                                   "f1();";
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"return x;",
        0 * kPointerSize,
        1,
-       3,
+       4,
        {
+           B(StackCheck),            //
            B(LdaLookupSlot), U8(0),  //
            B(Return)                 //
        },
@@ -6519,8 +7725,9 @@
       {"x = 10;",
        0 * kPointerSize,
        1,
-       6,
+       7,
        {
+           B(StackCheck),                  //
            B(LdaSmi8), U8(10),             //
            B(StaLookupSlotSloppy), U8(0),  //
            B(LdaUndefined),                //
@@ -6531,8 +7738,9 @@
       {"'use strict'; x = 10;",
        0 * kPointerSize,
        1,
-       6,
+       7,
        {
+           B(StackCheck),                  //
            B(LdaSmi8), U8(10),             //
            B(StaLookupSlotStrict), U8(0),  //
            B(LdaUndefined),                //
@@ -6543,8 +7751,9 @@
       {"return typeof x;",
        0 * kPointerSize,
        1,
-       4,
+       5,
        {
+           B(StackCheck),                        //
            B(LdaLookupSlotInsideTypeof), U8(0),  //
            B(TypeOf),                            //
            B(Return),                            //
@@ -6552,15 +7761,14 @@
        1,
        {"x"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     std::string script = std::string(function_prologue) +
                          std::string(snippets[i].code_snippet) +
                          std::string(function_epilogue);
-    // TODO(mythria): use * as filter when function declarations are supported
-    // inside eval.
     Handle<BytecodeArray> bytecode_array =
-        helper.MakeBytecode(script.c_str(), "t", "f");
+        helper.MakeBytecode(script.c_str(), "*", "f");
     CheckBytecodeArrayEqual(snippets[i], bytecode_array);
   }
 }
@@ -6581,13 +7789,15 @@
       "f1();";
 
   int const_count[] = {0, 0, 0, 0};
+  // clang-format off
   ExpectedSnippet<InstanceType, 257> snippets[] = {
       {REPEAT_256(SPACE, "var y = 2.3;")
        "return x;",
        1 * kPointerSize,
        1,
-       1028,
+       1029,
        {
+           B(StackCheck),                            //
            REPEAT_256(SPACE,                         //
              B(LdaConstant), U8(const_count[0]++),   //
              B(Star), R(0), )                        //
@@ -6601,8 +7811,9 @@
        "return typeof x;",
        1 * kPointerSize,
        1,
-       1029,
+       1030,
        {
+           B(StackCheck),                               //
            REPEAT_256(SPACE,                            //
              B(LdaConstant), U8(const_count[1]++),      //
              B(Star), R(0), )                           //
@@ -6617,8 +7828,9 @@
        "x = 10;",
        1 * kPointerSize,
        1,
-       1031,
+       1032,
        {
+           B(StackCheck),                           //
            REPEAT_256(SPACE,                        //
              B(LdaConstant), U8(const_count[2]++),  //
              B(Star), R(0), )                       //
@@ -6635,9 +7847,10 @@
        "x = 10;",
        1 * kPointerSize,
        1,
-       1031,
+       1032,
        {
-           REPEAT_256(SPACE,
+           B(StackCheck),                           //
+           REPEAT_256(SPACE,                        //
              B(LdaConstant), U8(const_count[3]++),  //
              B(Star), R(0), )                       //
            B(LdaSmi8), U8(10),                      //
@@ -6649,15 +7862,14 @@
        {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
         InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     std::string script = std::string(function_prologue) +
                          std::string(snippets[i].code_snippet) +
                          std::string(function_epilogue);
-    // TODO(mythria): use * as filter when function declarations are supported
-    // inside eval.
     Handle<BytecodeArray> bytecode_array =
-        helper.MakeBytecode(script.c_str(), "t", "f");
+        helper.MakeBytecode(script.c_str(), "*", "f");
     CheckBytecodeArrayEqual(snippets[i], bytecode_array);
   }
 }
@@ -6677,51 +7889,1215 @@
                                   "}"
                                   "f1();";
 
+  // clang-format off
   ExpectedSnippet<const char*> snippets[] = {
       {"delete x;",
-       0 * kPointerSize,
+       1 * kPointerSize,
        1,
-       5,
+       12,
        {
-           B(LdaConstant), U8(0),  //
-           B(DeleteLookupSlot),    //
-           B(LdaUndefined),        //
-           B(Return)               //
+           B(StackCheck),                                                 //
+           B(LdaConstant), U8(0),                                         //
+           B(Star), R(0),                                                 //
+           B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1),  //
+           B(LdaUndefined),                                               //
+           B(Return)                                                      //
        },
        1,
        {"x"}},
       {"return delete y;",
        0 * kPointerSize,
        1,
-       2,
+       3,
        {
+           B(StackCheck),      //
            B(LdaFalse),        //
            B(Return)           //
        },
        0},
       {"return delete z;",
-       0 * kPointerSize,
+       1 * kPointerSize,
        1,
-       4,
+       11,
        {
-           B(LdaConstant), U8(0),  //
-           B(DeleteLookupSlot),    //
-           B(Return)               //
+           B(StackCheck),                                                 //
+           B(LdaConstant), U8(0),                                         //
+           B(Star), R(0),                                                 //
+           B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1),  //
+           B(Return)                                                      //
        },
        1,
        {"z"}},
   };
+  // clang-format on
 
   for (size_t i = 0; i < arraysize(snippets); i++) {
     std::string script = std::string(function_prologue) +
                          std::string(snippets[i].code_snippet) +
                          std::string(function_epilogue);
     Handle<BytecodeArray> bytecode_array =
-        helper.MakeBytecode(script.c_str(), "t", "f");
+        helper.MakeBytecode(script.c_str(), "*", "f");
     CheckBytecodeArrayEqual(snippets[i], bytecode_array);
   }
 }
 
+TEST(WideRegisters) {
+  // Prepare prologue that creates frame for lots of registers.
+  std::ostringstream os;
+  for (size_t i = 0; i < 157; ++i) {
+    os << "var x" << i << ";\n";
+  }
+  std::string prologue(os.str());
+
+  // clang-format off
+  ExpectedSnippet<int> snippets[] = {
+      {"x0 = x127;\n"
+       "return x0;\n",
+       161 * kPointerSize,
+       1,
+       11,
+       {
+           B(StackCheck),                   //
+           B(MovWide), R16(131), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(Star), R(0),                   //
+           B(Return),                       //
+       }},
+      {"x127 = x126;\n"
+       "return x127;\n",
+       161 * kPointerSize,
+       1,
+       23,
+       {
+           B(StackCheck),                   //
+           B(MovWide), R16(130), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(131),  //
+           B(MovWide), R16(131), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(Return),                       //
+       }},
+      {"if (x2 > 3) { return x129; }\n"
+       "return x128;\n",
+       162 * kPointerSize,
+       1,
+       37,
+       {
+           B(StackCheck),                   //
+           B(Ldar), R(2),                   //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(161),  //
+           B(LdaSmi8), U8(3),               //
+           B(MovWide), R16(161), R16(125),  //
+           B(TestGreaterThan), R(125),      //
+           B(JumpIfFalse), U8(10),          //
+           B(MovWide), R16(133), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(Return),                       //
+           B(MovWide), R16(132), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(Return),                       //
+       }},
+      {"var x0 = 0;\n"
+       "if (x129 == 3) { var x129 = x0; }\n"
+       "if (x2 > 3) { return x0; }\n"
+       "return x129;\n",
+       162 * kPointerSize,
+       1,
+       69,
+       {
+           B(StackCheck),                   //
+           B(LdaZero),                      //
+           B(Star), R(0),                   //
+           B(MovWide), R16(133), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(161),  //
+           B(LdaSmi8), U8(3),               //
+           B(MovWide), R16(161), R16(125),  //
+           B(TestEqual), R(125),            //
+           B(JumpIfFalse), U8(11),          //
+           B(Ldar), R(0),                   //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(133),  //
+           B(Ldar), R(2),                   //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(161),  //
+           B(LdaSmi8), U8(3),               //
+           B(MovWide), R16(161), R16(125),  //
+           B(TestGreaterThan), R(125),      //
+           B(JumpIfFalse), U8(5),           //
+           B(Ldar), R(0),                   //
+           B(Return),                       //
+           B(MovWide), R16(133), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(Return),                       //
+       }},
+      {"var x0 = 0;\n"
+       "var x1 = 0;\n"
+       "for (x128 = 0; x128 < 64; x128++) {"
+       "  x1 += x128;"
+       "}"
+       "return x128;\n",
+       162 * kPointerSize,
+       1,
+       99,
+       {
+           B(StackCheck),                   //
+           B(LdaZero),                      //
+           B(Star), R(0),                   //
+           B(LdaZero),                      //
+           B(Star), R(1),                   //
+           B(LdaZero),                      //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(132),  //
+           B(MovWide), R16(132), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(161),  //
+           B(LdaSmi8), U8(64),              //
+           B(MovWide), R16(161), R16(125),  //
+           B(TestLessThan), R(125),         //
+           B(JumpIfFalse), U8(53),          //
+           B(StackCheck),                   //
+           B(Ldar), R(1),                   //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(161),  //
+           B(MovWide), R16(132), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(MovWide), R16(161), R16(125),  //
+           B(Add), R(125),                  //
+           B(Star), R(1),                   //
+           B(MovWide), R16(132), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(ToNumber),                     //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(161),  //
+           B(Inc),                          //
+           B(Star), R(125),                 //
+           B(MovWide), R16(125), R16(132),  //
+           B(Jump), U8(-74),                //
+           B(MovWide), R16(132), R16(125),  //
+           B(Ldar), R(125),                 //
+           B(Return),                       //
+       }},
+      {"var x0 = 1234;\n"
+       "var x1 = 0;\n"
+       "for (x128 in x0) {"
+       "  x1 += x128;"
+       "}"
+       "return x1;\n",
+       167 * kPointerSize,
+       1,
+       111,
+       {
+           B(StackCheck),                                   //
+           B(LdaConstant), U8(0),                           //
+           B(Star), R(0),                                   //
+           B(LdaZero),                                      //
+           B(Star), R(1),                                   //
+           B(Ldar), R(0),                                   //
+           B(JumpIfUndefined), U8(98),                      //
+           B(JumpIfNull), U8(96),                           //
+           B(ToObject),                                     //
+           B(JumpIfNull), U8(93),                           //
+           B(Star), R(125),                                 //
+           B(MovWide), R16(125), R16(161),                  //
+           B(ForInPrepareWide), R16(162),                   //
+           B(LdaZero),                                      //
+           B(Star), R(125),                                 //
+           B(MovWide), R16(125), R16(165),                  //
+           B(MovWide), R16(165), R16(125),                  //
+           B(MovWide), R16(164), R16(126),                  //
+           B(ForInDone), R(125), R(126),                    //
+           B(JumpIfTrue), U8(60),                           //
+           B(ForInNextWide), R16(161), R16(165), R16(162),  //
+           B(JumpIfUndefined), U8(35),                      //
+           B(Star), R(125),                                 //
+           B(MovWide), R16(125), R16(132),                  //
+           B(StackCheck),                                   //
+           B(Ldar), R(1),                                   //
+           B(Star), R(125),                                 //
+           B(MovWide), R16(125), R16(166),                  //
+           B(MovWide), R16(132), R16(125),                  //
+           B(Ldar), R(125),                                 //
+           B(MovWide), R16(166), R16(125),                  //
+           B(Add), R(125),                                  //
+           B(Star), R(1),                                   //
+           B(MovWide), R16(165), R16(125),                  //
+           B(ForInStep), R(125),                            //
+           B(Star), R(125),                                 //
+           B(MovWide), R16(125), R16(165),                  //
+           B(Jump), U8(-71),                                //
+           B(Ldar), R(1),                                   //
+           B(Return),                                       //
+       },
+       1,
+       {1234}},
+      {"x0 = %Add(x64, x63);\n"
+       "x1 = %Add(x27, x143);\n"
+       "%TheHole();\n"
+       "return x1;\n",
+       163 * kPointerSize,
+       1,
+       66,
+       {
+           B(StackCheck),                                            //
+           B(Ldar), R(64),                                           //
+           B(Star), R(125),                                          //
+           B(MovWide), R16(125), R16(161),                           //
+           B(Ldar), R(63),                                           //
+           B(Star), R(125),                                          //
+           B(MovWide), R16(125), R16(162),                           //
+           B(CallRuntimeWide), U16(Runtime::kAdd), R16(161), U8(2),  //
+           B(Star), R(0),                                            //
+           B(Ldar), R(27),                                           //
+           B(Star), R(125),                                          //
+           B(MovWide), R16(125), R16(161),                           //
+           B(MovWide), R16(147), R16(125),                           //
+           B(Ldar), R(125),                                          //
+           B(Star), R(125),                                          //
+           B(MovWide), R16(125), R16(162),                           //
+           B(CallRuntimeWide), U16(Runtime::kAdd), R16(161), U8(2),  //
+           B(Star), R(1),                                            //
+           B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0),      //
+           B(Ldar), R(1),                                            //
+           B(Return),                                                //
+       }}
+  };
+  // clang-format on
+
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+
+  for (size_t i = 0; i < arraysize(snippets); ++i) {
+    std::string body = prologue + snippets[i].code_snippet;
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(body.c_str());
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+}
+
+TEST(ConstVariable) {
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+  // clang-format off
+  ExpectedSnippet<const char*> snippets[] = {
+      {"const x = 10;",
+       1 * kPointerSize,
+       1,
+       10,
+       {
+           B(LdaTheHole),       //
+           B(Star), R(0),       //
+           B(StackCheck),       //
+           B(LdaSmi8), U8(10),  //
+           B(Star), R(0),       //
+           B(LdaUndefined),     //
+           B(Return)            //
+       },
+       0},
+      {"const x = 10; return x;",
+       2 * kPointerSize,
+       1,
+       20,
+       {
+           B(LdaTheHole),                                                    //
+           B(Star), R(0),                                                    //
+           B(StackCheck),                                                    //
+           B(LdaSmi8), 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)                                                         //
+       },
+       1,
+       {"x"}},
+      {"const x = ( x = 20);",
+       3 * kPointerSize,
+       1,
+       32,
+       {
+           B(LdaTheHole),                                                    //
+           B(Star), R(0),                                                    //
+           B(StackCheck),                                                    //
+           B(LdaSmi8), 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)                                                         //
+       },
+       1,
+       {"x"}},
+      {"const x = 10; x = 20;",
+       3 * kPointerSize,
+       1,
+       36,
+       {
+           B(LdaTheHole),                                                    //
+           B(Star), R(0),                                                    //
+           B(StackCheck),                                                    //
+           B(LdaSmi8), U8(10),                                               //
+           B(Star), R(0),                                                    //
+           B(LdaSmi8), 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)                                                         //
+       },
+       1,
+       {"x"}},
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+}
+
+TEST(LetVariable) {
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+
+  // clang-format off
+  ExpectedSnippet<const char*> snippets[] = {
+      {"let x = 10;",
+       1 * kPointerSize,
+       1,
+       10,
+       {
+           B(LdaTheHole),       //
+           B(Star), R(0),       //
+           B(StackCheck),       //
+           B(LdaSmi8), U8(10),  //
+           B(Star), R(0),       //
+           B(LdaUndefined),     //
+           B(Return)            //
+       },
+       0},
+      {"let x = 10; return x;",
+       2 * kPointerSize,
+       1,
+       20,
+       {
+           B(LdaTheHole),                                                    //
+           B(Star), R(0),                                                    //
+           B(StackCheck),                                                    //
+           B(LdaSmi8), 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)                                                         //
+       },
+       1,
+       {"x"}},
+      {"let x = (x = 20);",
+       3 * kPointerSize,
+       1,
+       27,
+       {
+           B(LdaTheHole),                                                    //
+           B(Star), R(0),                                                    //
+           B(StackCheck),                                                    //
+           B(LdaSmi8), 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)                                                         //
+       },
+       1,
+       {"x"}},
+      {"let x = 10; x = 20;",
+       3 * kPointerSize,
+       1,
+       31,
+       {
+           B(LdaTheHole),                                                    //
+           B(Star), R(0),                                                    //
+           B(StackCheck),                                                    //
+           B(LdaSmi8), U8(10),                                               //
+           B(Star), R(0),                                                    //
+           B(LdaSmi8), 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)                                                         //
+       },
+       1,
+       {"x"}},
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+}
+
+TEST(LegacyConstVariable) {
+  bool old_legacy_const_flag = FLAG_legacy_const;
+  FLAG_legacy_const = true;
+
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+
+  // clang-format off
+  ExpectedSnippet<const char*> snippets[] = {
+      {"const x = 10;",
+       2 * kPointerSize,
+       1,
+       19,
+       {
+           B(LdaTheHole),            //
+           B(Star), R(0),            //
+           B(StackCheck),            //
+           B(LdaSmi8), U8(10),       //
+           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)                 //
+       },
+       0},
+      {"const x = 10; return x;",
+       2 * kPointerSize,
+       1,
+       23,
+       {
+           B(LdaTheHole),            //
+           B(Star), R(0),            //
+           B(StackCheck),            //
+           B(LdaSmi8), U8(10),       //
+           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)                 //
+       },
+       0},
+      {"const x = ( x = 20);",
+       2 * kPointerSize,
+       1,
+       23,
+       {
+           B(LdaTheHole),            //
+           B(Star), R(0),            //
+           B(StackCheck),            //
+           B(LdaSmi8), U8(20),       //
+           B(Star), R(1),            //
+           B(Ldar), R(0),            //
+           B(Ldar), R(1),            //
+           B(Ldar), R(0),            //
+           B(JumpIfNotHole), U8(5),  //
+           B(Mov), R(1), R(0),       //
+           B(Ldar), R(1),            //
+           B(LdaUndefined),          //
+           B(Return)                 //
+       },
+       0},
+      {"const x = 10; x = 20;",
+       2 * kPointerSize,
+       1,
+       27,
+       {
+           B(LdaTheHole),            //
+           B(Star), R(0),            //
+           B(StackCheck),            //
+           B(LdaSmi8), U8(10),       //
+           B(Star), R(1),            //
+           B(Ldar), R(0),            //
+           B(JumpIfNotHole), U8(5),  //
+           B(Mov), R(1), R(0),       //
+           B(Ldar), R(1),            //
+           B(LdaSmi8), U8(20),       //
+           B(Star), R(1),            //
+           B(Ldar), R(0),            //
+           B(Ldar), R(1),            //
+           B(LdaUndefined),          //
+           B(Return)                 //
+       },
+       0},
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+
+  FLAG_legacy_const = old_legacy_const_flag;
+}
+
+TEST(ConstVariableContextSlot) {
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+
+  int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
+
+  // TODO(mythria): Add tests for initialization of this via super calls.
+  // TODO(mythria): Add tests that walk the context chain.
+  // clang-format off
+  ExpectedSnippet<InstanceType> snippets[] = {
+      {"const x = 10; function f1() {return x;}",
+       2 * kPointerSize,
+       1,
+       24,
+       {
+           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(LdaSmi8), U8(10),                                             //
+           B(StaContextSlot), R(context), U8(4),                           //
+           B(LdaUndefined),                                                //
+           B(Return)                                                       //
+       },
+       1,
+       {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+      {"const x = 10; function f1() {return x;} return x;",
+       3 * kPointerSize,
+       1,
+       37,
+       {
+           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(LdaSmi8), 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)                                                         //
+       },
+       2,
+       {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+      {"const x = (x = 20); function f1() {return x;}",
+       4 * kPointerSize,
+       1,
+       50,
+       {
+           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(LdaSmi8), 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)                                                         //
+       },
+       2,
+       {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+      {"const x = 10; x = 20; function f1() {return x;}",
+       4 * kPointerSize,
+       1,
+       52,
+       {
+           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(LdaSmi8), U8(10),                                               //
+           B(StaContextSlot), R(context), U8(4),                             //
+           B(LdaSmi8), 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)                                                         //
+       },
+       2,
+       {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+}
+
+TEST(LetVariableContextSlot) {
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+
+  int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
+
+  // clang-format off
+  ExpectedSnippet<InstanceType> snippets[] = {
+      {"let x = 10; function f1() {return x;}",
+       2 * kPointerSize,
+       1,
+       24,
+       {
+           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(LdaSmi8), U8(10),                                             //
+           B(StaContextSlot), R(context), U8(4),                           //
+           B(LdaUndefined),                                                //
+           B(Return)                                                       //
+       },
+       1,
+       {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+      {"let x = 10; function f1() {return x;} return x;",
+       3 * kPointerSize,
+       1,
+       37,
+       {
+           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(LdaSmi8), 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)                                                         //
+       },
+       2,
+       {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+      {"let x = (x = 20); function f1() {return x;}",
+       4 * kPointerSize,
+       1,
+       45,
+       {
+           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(LdaSmi8), 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)                                                         //
+       },
+       2,
+       {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+      {"let x = 10; x = 20; function f1() {return x;}",
+       4 * kPointerSize,
+       1,
+       47,
+       {
+           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(LdaSmi8), U8(10),                                               //
+           B(StaContextSlot), R(context), U8(4),                             //
+           B(LdaSmi8), 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)                                                         //
+       },
+       2,
+       {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+}
+
+TEST(DoExpression) {
+  bool old_flag = FLAG_harmony_do_expressions;
+  FLAG_harmony_do_expressions = true;
+
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+
+  // clang-format off
+  ExpectedSnippet<const char*> snippets[] = {
+      {"var a = do { }; return a;",
+       2 * kPointerSize,
+       1,
+       6,
+       {
+           B(StackCheck),  //
+           B(Ldar), R(0),  //
+           B(Star), R(1),  //
+           B(Return)       //
+       },
+       0},
+      {"var a = do { var x = 100; }; return a;",
+       3 * kPointerSize,
+       1,
+       11,
+       {
+           B(StackCheck),        //
+           B(LdaSmi8), U8(100),  //
+           B(Star), R(1),        //
+           B(LdaUndefined),      //
+           B(Star), R(0),        //
+           B(Star), R(2),        //
+           B(Return)             //
+       },
+       0},
+      {"while(true) { var a = 10; a = do { ++a; break; }; a = 20; }",
+       2 * kPointerSize,
+       1,
+       26,
+       {
+           B(StackCheck),             //
+           B(StackCheck),             //
+           B(LdaSmi8), 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(LdaSmi8), U8(20),        //
+           B(Star), R(1),             //
+           B(Jump), U8(-21),          //
+           B(LdaUndefined),           //
+           B(Return),                 //
+       },
+       0},
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+  FLAG_harmony_do_expressions = old_flag;
+}
+
+TEST(WithStatement) {
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+
+  int deep_elements_flags =
+      ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+  int context = Register::current_context().index();
+  int closure = Register::function_closure().index();
+  int new_target = Register::new_target().index();
+
+  // clang-format off
+  ExpectedSnippet<InstanceType> snippets[] = {
+      {"with ({x:42}) { return x; }",
+       5 * kPointerSize,
+       1,
+       47,
+       {
+           B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure),  //
+           /*           */ U8(1),                                          //
+           B(PushContext), R(0),                                           //
+           B(Ldar), THIS(1),                                               //
+           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(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags),  //
+           B(Star), R(2),                                                  //
+           B(ToObject),                                                    //
+           B(Star), R(3),                                                  //
+           B(Ldar), R(closure),                                            //
+           B(Star), R(4),                                                  //
+           B(CallRuntime), U16(Runtime::kPushWithContext), R(3), U8(2),    //
+           B(PushContext), R(1),                                           //
+           B(LdaLookupSlot), U8(1),                                        //
+           B(PopContext), R(0),                                            //
+           B(Return),                                                      //
+       },
+       2,
+       {InstanceType::FIXED_ARRAY_TYPE,
+        InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+}
+
+TEST(DoDebugger) {
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+
+  // clang-format off
+  ExpectedSnippet<const char*> snippet = {
+      "debugger;",
+       0,
+       1,
+       4,
+       {
+           B(StackCheck),    //
+           B(Debugger),      //
+           B(LdaUndefined),  //
+           B(Return)         //
+       },
+       0
+  };
+  // clang-format on
+
+  Handle<BytecodeArray> bytecode_array =
+      helper.MakeBytecodeForFunctionBody(snippet.code_snippet);
+  CheckBytecodeArrayEqual(snippet, bytecode_array);
+}
+
+// TODO(rmcilroy): Update expectations after switch to
+// Runtime::kDefineDataPropertyInLiteral.
+TEST(ClassDeclarations) {
+  InitializedHandleScope handle_scope;
+  BytecodeGeneratorHelper helper;
+
+  int closure = Register::function_closure().index();
+  int context = Register::current_context().index();
+
+  // clang-format off
+  ExpectedSnippet<InstanceType, 12> snippets[] = {
+    {"class Person {\n"
+     "  constructor(name) { this.name = name; }\n"
+     "  speak() { console.log(this.name + ' is speaking.'); }\n"
+     "}\n",
+     9 * kPointerSize,
+     1,
+     71,
+     {
+       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(LdaSmi8), U8(15),                                                   //
+       B(Star), R(4),                                                        //
+       B(LdaConstant), U8(1),                                                //
+       B(Star), R(5),                                                        //
+       B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),              //
+       B(Star), R(2),                                                        //
+       B(LoadIC), R(2), U8(2), U8(1),                                  //
+       B(Star), R(3),                                                        //
+       B(Mov), R(3), R(4),                                                   //
+       B(LdaConstant), U8(3),                                                //
+       B(Star), R(5),                                                        //
+       B(CreateClosure), U8(4), U8(0),                                       //
+       B(Star), R(6),                                                        //
+       B(LdaSmi8), 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)                                                             //
+     },
+     5,
+     { InstanceType::SHARED_FUNCTION_INFO_TYPE, kInstanceTypeDontCare,
+       InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+       InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+       InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+    {"class person {\n"
+     "  constructor(name) { this.name = name; }\n"
+     "  speak() { console.log(this.name + ' is speaking.'); }\n"
+     "}\n",
+     9 * kPointerSize,
+     1,
+     71,
+     {
+       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(LdaSmi8), U8(15),                                                   //
+       B(Star), R(4),                                                        //
+       B(LdaConstant), U8(1),                                                //
+       B(Star), R(5),                                                        //
+       B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),              //
+       B(Star), R(2),                                                        //
+       B(LoadIC), R(2), U8(2), U8(1),                                  //
+       B(Star), R(3),                                                        //
+       B(Mov), R(3), R(4),                                                   //
+       B(LdaConstant), U8(3),                                                //
+       B(Star), R(5),                                                        //
+       B(CreateClosure), U8(4), U8(0),                                       //
+       B(Star), R(6),                                                        //
+       B(LdaSmi8), 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)                                                             //
+     },
+     5,
+     { InstanceType::SHARED_FUNCTION_INFO_TYPE, kInstanceTypeDontCare,
+       InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+       InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+       InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+    {"var n0 = 'a';"
+     "var n1 = 'b';"
+     "class N {\n"
+     "  [n0]() { return n0; }\n"
+     "  static [n1]() { return n1; }\n"
+     "}\n",
+     10 * kPointerSize,
+     1,
+     125,
+     {
+       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(LdaSmi8), U8(41),                                                   //
+       B(Star), R(5),                                                        //
+       B(LdaSmi8), U8(107),                                                  //
+       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(LdaSmi8), U8(2),                                                    //
+       B(Star), R(8),                                                        //
+       B(LdaSmi8), 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(LdaSmi8), 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),                                                            //
+     },
+     6,
+     { InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+       InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+       InstanceType::SHARED_FUNCTION_INFO_TYPE,
+       InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+       InstanceType::SHARED_FUNCTION_INFO_TYPE,
+       InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+    {"var count = 0;\n"
+     "class C { constructor() { count++; }}\n"
+     "return new C();\n",
+     10 * kPointerSize,
+     1,
+     74,
+     {
+       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(LdaSmi8), U8(30),                                                    //
+       B(Star), R(5),                                                         //
+       B(LdaSmi8), U8(67),                                                    //
+       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),                                                             //
+     },
+     3,
+     { InstanceType::SHARED_FUNCTION_INFO_TYPE,
+       InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+       InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < arraysize(snippets); i++) {
+    Handle<BytecodeArray> bytecode_array =
+        helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+    CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+  }
+}
+
+// TODO(oth): Add tests for super keyword.
+
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc
index 506cf00..69cf0e1 100644
--- a/test/cctest/interpreter/test-interpreter.cc
+++ b/test/cctest/interpreter/test-interpreter.cc
@@ -65,8 +65,6 @@
         bytecode_(bytecode),
         feedback_vector_(feedback_vector) {
     i::FLAG_ignition = true;
-    i::FLAG_ignition_fake_try_catch = true;
-    i::FLAG_ignition_fallback_on_eval_and_catch = false;
     i::FLAG_always_opt = false;
     // Set ignition filter flag via SetFlagsFromString to avoid double-free
     // (or potential leak with StrDup() based on ownership confusion).
@@ -98,6 +96,18 @@
     return InterpreterCallable<A...>(isolate_, GetBytecodeFunction<A...>());
   }
 
+  Local<Message> CheckThrowsReturnMessage() {
+    TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
+    auto callable = GetCallable<>();
+    MaybeHandle<Object> no_result = callable();
+    CHECK(isolate_->has_pending_exception());
+    CHECK(try_catch.HasCaught());
+    CHECK(no_result.is_null());
+    isolate_->OptionalRescheduleException(true);
+    CHECK(!try_catch.Message().IsEmpty());
+    return try_catch.Message();
+  }
+
   static Handle<Object> NewObject(const char* script) {
     return v8::Utils::OpenHandle(*CompileRun(script));
   }
@@ -165,10 +175,8 @@
   Handle<Object> undefined_value =
       handles.main_isolate()->factory()->undefined_value();
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 0);
   builder.Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -184,10 +192,8 @@
   Handle<Object> undefined_value =
       handles.main_isolate()->factory()->undefined_value();
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 0);
   builder.LoadUndefined().Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -202,10 +208,8 @@
   HandleAndZoneScope handles;
   Handle<Object> null_value = handles.main_isolate()->factory()->null_value();
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 0);
   builder.LoadNull().Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -221,10 +225,8 @@
   Handle<Object> the_hole_value =
       handles.main_isolate()->factory()->the_hole_value();
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 0);
   builder.LoadTheHole().Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -239,10 +241,8 @@
   HandleAndZoneScope handles;
   Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 0);
   builder.LoadTrue().Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -257,10 +257,8 @@
   HandleAndZoneScope handles;
   Handle<Object> false_value = handles.main_isolate()->factory()->false_value();
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 0);
   builder.LoadFalse().Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -277,10 +275,8 @@
 
   // Small Smis.
   for (int i = -128; i < 128; i++) {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(0);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                                 0, 0);
     builder.LoadLiteral(Smi::FromInt(i)).Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -292,10 +288,8 @@
 
   // Large Smis.
   {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(0);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                                 0, 0);
     builder.LoadLiteral(Smi::FromInt(0x12345678)).Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -307,10 +301,8 @@
 
   // Heap numbers.
   {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(0);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                                 0, 0);
     builder.LoadLiteral(factory->NewHeapNumber(-2.1e19)).Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -322,10 +314,8 @@
 
   // Strings.
   {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(0);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
+    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();
@@ -342,10 +332,8 @@
   HandleAndZoneScope handles;
   Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
   for (int i = 0; i <= kMaxInt8; i++) {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(i + 1);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                                 0, i + 1);
     Register reg(i);
     builder.LoadTrue()
         .StoreAccumulatorInRegister(reg)
@@ -362,117 +350,6 @@
 }
 
 
-TEST(InterpreterExchangeRegisters) {
-  for (int locals_count = 2; locals_count < 300; locals_count += 126) {
-    HandleAndZoneScope handles;
-    for (int exchanges = 1; exchanges < 4; exchanges++) {
-      BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-      builder.set_locals_count(locals_count);
-      builder.set_context_count(0);
-      builder.set_parameter_count(0);
-
-      Register r0(0);
-      Register r1(locals_count - 1);
-      builder.LoadTrue();
-      builder.StoreAccumulatorInRegister(r0);
-      builder.ExchangeRegisters(r0, r1);
-      builder.LoadFalse();
-      builder.StoreAccumulatorInRegister(r0);
-
-      bool expected = false;
-      for (int i = 0; i < exchanges; i++) {
-        builder.ExchangeRegisters(r0, r1);
-        expected = !expected;
-      }
-      builder.LoadAccumulatorWithRegister(r0);
-      builder.Return();
-      Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
-      InterpreterTester tester(handles.main_isolate(), bytecode_array);
-      auto callable = tester.GetCallable<>();
-      Handle<Object> return_val = callable().ToHandleChecked();
-      Handle<Object> expected_val =
-          handles.main_isolate()->factory()->ToBoolean(expected);
-      CHECK(return_val.is_identical_to(expected_val));
-    }
-  }
-}
-
-
-TEST(InterpreterExchangeRegistersWithParameter) {
-  for (int locals_count = 2; locals_count < 300; locals_count += 126) {
-    HandleAndZoneScope handles;
-    for (int exchanges = 1; exchanges < 4; exchanges++) {
-      BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-      builder.set_locals_count(locals_count);
-      builder.set_context_count(0);
-      builder.set_parameter_count(3);
-
-      Register r0 = Register::FromParameterIndex(2, 3);
-      Register r1(locals_count - 1);
-      builder.LoadTrue();
-      builder.StoreAccumulatorInRegister(r0);
-      builder.ExchangeRegisters(r0, r1);
-      builder.LoadFalse();
-      builder.StoreAccumulatorInRegister(r0);
-
-      bool expected = false;
-      for (int i = 0; i < exchanges; i++) {
-        builder.ExchangeRegisters(r0, r1);
-        expected = !expected;
-      }
-      builder.LoadAccumulatorWithRegister(r0);
-      builder.Return();
-      Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
-      InterpreterTester tester(handles.main_isolate(), bytecode_array);
-      auto callable = tester.GetCallable<>();
-      Handle<Object> return_val = callable().ToHandleChecked();
-      Handle<Object> expected_val =
-          handles.main_isolate()->factory()->ToBoolean(expected);
-      CHECK(return_val.is_identical_to(expected_val));
-    }
-  }
-}
-
-
-TEST(InterpreterExchangeWideRegisters) {
-  for (int locals_count = 3; locals_count < 300; locals_count += 126) {
-    HandleAndZoneScope handles;
-    for (int exchanges = 0; exchanges < 7; exchanges++) {
-      BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-      builder.set_locals_count(locals_count);
-      builder.set_context_count(0);
-      builder.set_parameter_count(0);
-
-      Register r0(0);
-      Register r1(locals_count - 1);
-      Register r2(locals_count - 2);
-      builder.LoadLiteral(Smi::FromInt(200));
-      builder.StoreAccumulatorInRegister(r0);
-      builder.ExchangeRegisters(r0, r1);
-      builder.LoadLiteral(Smi::FromInt(100));
-      builder.StoreAccumulatorInRegister(r0);
-      builder.ExchangeRegisters(r0, r2);
-      builder.LoadLiteral(Smi::FromInt(0));
-      builder.StoreAccumulatorInRegister(r0);
-      for (int i = 0; i < exchanges; i++) {
-        builder.ExchangeRegisters(r1, r2);
-        builder.ExchangeRegisters(r0, r1);
-      }
-      builder.LoadAccumulatorWithRegister(r0);
-      builder.Return();
-      Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
-      InterpreterTester tester(handles.main_isolate(), bytecode_array);
-      auto callable = tester.GetCallable<>();
-      Handle<Object> return_val = callable().ToHandleChecked();
-      Handle<Object> expected_val =
-          handles.main_isolate()->factory()->NewNumberFromInt(100 *
-                                                              (exchanges % 3));
-      CHECK(return_val.is_identical_to(expected_val));
-    }
-  }
-}
-
-
 static const Token::Value kShiftOperators[] = {
     Token::Value::SHL, Token::Value::SAR, Token::Value::SHR};
 
@@ -539,17 +416,14 @@
         HandleAndZoneScope handles;
         i::Factory* factory = handles.main_isolate()->factory();
         BytecodeArrayBuilder builder(handles.main_isolate(),
-                                     handles.main_zone());
-        builder.set_locals_count(1);
-        builder.set_context_count(0);
-        builder.set_parameter_count(1);
+                                     handles.main_zone(), 1, 0, 1);
         Register reg(0);
         int lhs = lhs_inputs[l];
         int rhs = rhs_inputs[r];
         builder.LoadLiteral(Smi::FromInt(lhs))
             .StoreAccumulatorInRegister(reg)
             .LoadLiteral(Smi::FromInt(rhs))
-            .BinaryOperation(kShiftOperators[o], reg, Strength::WEAK)
+            .BinaryOperation(kShiftOperators[o], reg)
             .Return();
         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -574,17 +448,14 @@
         HandleAndZoneScope handles;
         i::Factory* factory = handles.main_isolate()->factory();
         BytecodeArrayBuilder builder(handles.main_isolate(),
-                                     handles.main_zone());
-        builder.set_locals_count(1);
-        builder.set_context_count(0);
-        builder.set_parameter_count(1);
+                                     handles.main_zone(), 1, 0, 1);
         Register reg(0);
         int lhs = lhs_inputs[l];
         int rhs = rhs_inputs[r];
         builder.LoadLiteral(Smi::FromInt(lhs))
             .StoreAccumulatorInRegister(reg)
             .LoadLiteral(Smi::FromInt(rhs))
-            .BinaryOperation(kArithmeticOperators[o], reg, Strength::WEAK)
+            .BinaryOperation(kArithmeticOperators[o], reg)
             .Return();
         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -610,17 +481,14 @@
         HandleAndZoneScope handles;
         i::Factory* factory = handles.main_isolate()->factory();
         BytecodeArrayBuilder builder(handles.main_isolate(),
-                                     handles.main_zone());
-        builder.set_locals_count(1);
-        builder.set_context_count(0);
-        builder.set_parameter_count(1);
+                                     handles.main_zone(), 1, 0, 1);
         Register reg(0);
         double lhs = lhs_inputs[l];
         double rhs = rhs_inputs[r];
         builder.LoadLiteral(factory->NewNumber(lhs))
             .StoreAccumulatorInRegister(reg)
             .LoadLiteral(factory->NewNumber(rhs))
-            .BinaryOperation(kArithmeticOperators[o], reg, Strength::WEAK)
+            .BinaryOperation(kArithmeticOperators[o], reg)
             .Return();
         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -669,15 +537,13 @@
   };
 
   for (size_t i = 0; i < arraysize(test_cases); i++) {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(1);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                                 0, 1);
     Register reg(0);
     builder.LoadLiteral(test_cases[i].lhs)
         .StoreAccumulatorInRegister(reg)
         .LoadLiteral(test_cases[i].rhs)
-        .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+        .BinaryOperation(Token::Value::ADD, reg)
         .Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -691,10 +557,8 @@
 
 TEST(InterpreterParameter1) {
   HandleAndZoneScope handles;
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 0);
   builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -715,18 +579,16 @@
 
 TEST(InterpreterParameter8) {
   HandleAndZoneScope handles;
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(8);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 8,
+                               0, 0);
   builder.LoadAccumulatorWithRegister(builder.Parameter(0))
-      .BinaryOperation(Token::Value::ADD, builder.Parameter(1), Strength::WEAK)
-      .BinaryOperation(Token::Value::ADD, builder.Parameter(2), Strength::WEAK)
-      .BinaryOperation(Token::Value::ADD, builder.Parameter(3), Strength::WEAK)
-      .BinaryOperation(Token::Value::ADD, builder.Parameter(4), Strength::WEAK)
-      .BinaryOperation(Token::Value::ADD, builder.Parameter(5), Strength::WEAK)
-      .BinaryOperation(Token::Value::ADD, builder.Parameter(6), Strength::WEAK)
-      .BinaryOperation(Token::Value::ADD, builder.Parameter(7), Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, builder.Parameter(1))
+      .BinaryOperation(Token::Value::ADD, builder.Parameter(2))
+      .BinaryOperation(Token::Value::ADD, builder.Parameter(3))
+      .BinaryOperation(Token::Value::ADD, builder.Parameter(4))
+      .BinaryOperation(Token::Value::ADD, builder.Parameter(5))
+      .BinaryOperation(Token::Value::ADD, builder.Parameter(6))
+      .BinaryOperation(Token::Value::ADD, builder.Parameter(7))
       .Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -752,10 +614,8 @@
 
 TEST(InterpreterParameter1Assign) {
   HandleAndZoneScope handles;
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 0);
   builder.LoadLiteral(Smi::FromInt(5))
       .StoreAccumulatorInRegister(builder.Parameter(0))
       .LoadAccumulatorWithRegister(builder.Parameter(0))
@@ -882,12 +742,9 @@
   Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
   name = factory->string_table()->LookupString(isolate, name);
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
-  builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
-                            i::SLOPPY)
+  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();
 
@@ -938,13 +795,10 @@
   Handle<i::String> key = factory->NewStringFromAsciiChecked("key");
   key = factory->string_table()->LookupString(isolate, key);
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(1);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 1);
   builder.LoadLiteral(key)
-      .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot),
-                         i::STRICT)
+      .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot))
       .Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -983,10 +837,8 @@
   Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
   name = factory->string_table()->LookupString(isolate, name);
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  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)
@@ -1044,10 +896,8 @@
   Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
   name = factory->string_table()->LookupString(isolate, name);
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(1);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 1);
   builder.LoadLiteral(name)
       .StoreAccumulatorInRegister(Register(0))
       .LoadLiteral(Smi::FromInt(999))
@@ -1078,8 +928,7 @@
   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
 }
 
-
-TEST(InterpreterCall) {
+static void TestInterpreterCall(TailCallMode tail_call_mode) {
   HandleAndZoneScope handles;
   i::Isolate* isolate = handles.main_isolate();
   i::Factory* factory = isolate->factory();
@@ -1097,13 +946,11 @@
 
   // Check with no args.
   {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(1);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
-    builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+    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), 0, 0)
+        .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
         .Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -1118,13 +965,11 @@
 
   // Check that receiver is passed properly.
   {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(1);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
-    builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+    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), 0, 0)
+        .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
         .Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -1142,11 +987,9 @@
 
   // Check with two parameters (+ receiver).
   {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(4);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
-    builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+    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))
         .StoreAccumulatorInRegister(Register(1))
@@ -1154,7 +997,7 @@
         .StoreAccumulatorInRegister(Register(2))
         .LoadLiteral(Smi::FromInt(11))
         .StoreAccumulatorInRegister(Register(3))
-        .Call(Register(0), Register(1), 2, 0)
+        .Call(Register(0), Register(1), 3, 0, tail_call_mode)
         .Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -1171,11 +1014,9 @@
 
   // Check with 10 parameters (+ receiver).
   {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-    builder.set_locals_count(12);
-    builder.set_context_count(0);
-    builder.set_parameter_count(1);
-    builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+    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))
         .StoreAccumulatorInRegister(Register(1))
@@ -1199,7 +1040,7 @@
         .StoreAccumulatorInRegister(Register(10))
         .LoadLiteral(factory->NewStringFromAsciiChecked("j"))
         .StoreAccumulatorInRegister(Register(11))
-        .Call(Register(0), Register(1), 10, 0)
+        .Call(Register(0), Register(1), 11, 0, tail_call_mode)
         .Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -1220,6 +1061,9 @@
   }
 }
 
+TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow); }
+
+TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow); }
 
 static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder,
                                          Register reg, int value,
@@ -1236,7 +1080,7 @@
                                                Register scratch) {
   return builder.StoreAccumulatorInRegister(scratch)
       .LoadLiteral(Smi::FromInt(value))
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .StoreAccumulatorInRegister(reg)
       .LoadAccumulatorWithRegister(scratch);
 }
@@ -1244,10 +1088,8 @@
 
 TEST(InterpreterJumps) {
   HandleAndZoneScope handles;
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(2);
-  builder.set_context_count(0);
-  builder.set_parameter_count(0);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+                               0, 2);
   Register reg(0), scratch(1);
   BytecodeLabel label[3];
 
@@ -1273,10 +1115,8 @@
 
 TEST(InterpreterConditionalJumps) {
   HandleAndZoneScope handles;
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(2);
-  builder.set_context_count(0);
-  builder.set_parameter_count(0);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+                               0, 2);
   Register reg(0), scratch(1);
   BytecodeLabel label[2];
   BytecodeLabel done, done1;
@@ -1309,10 +1149,8 @@
 TEST(InterpreterConditionalJumps2) {
   // TODO(oth): Add tests for all conditional jumps near and far.
   HandleAndZoneScope handles;
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(2);
-  builder.set_context_count(0);
-  builder.set_parameter_count(0);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+                               0, 2);
   Register reg(0), scratch(1);
   BytecodeLabel label[2];
   BytecodeLabel done, done1;
@@ -1397,15 +1235,12 @@
       for (size_t j = 0; j < arraysize(inputs); j++) {
         HandleAndZoneScope handles;
         BytecodeArrayBuilder builder(handles.main_isolate(),
-                                     handles.main_zone());
+                                     handles.main_zone(), 0, 0, 1);
         Register r0(0);
-        builder.set_locals_count(1);
-        builder.set_context_count(0);
-        builder.set_parameter_count(0);
         builder.LoadLiteral(Smi::FromInt(inputs[i]))
             .StoreAccumulatorInRegister(r0)
             .LoadLiteral(Smi::FromInt(inputs[j]))
-            .CompareOperation(comparison, r0, Strength::WEAK)
+            .CompareOperation(comparison, r0)
             .Return();
 
         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1436,15 +1271,12 @@
         HandleAndZoneScope handles;
         i::Factory* factory = handles.main_isolate()->factory();
         BytecodeArrayBuilder builder(handles.main_isolate(),
-                                     handles.main_zone());
+                                     handles.main_zone(), 0, 0, 1);
         Register r0(0);
-        builder.set_locals_count(1);
-        builder.set_context_count(0);
-        builder.set_parameter_count(0);
         builder.LoadLiteral(factory->NewHeapNumber(inputs[i]))
             .StoreAccumulatorInRegister(r0)
             .LoadLiteral(factory->NewHeapNumber(inputs[j]))
-            .CompareOperation(comparison, r0, Strength::WEAK)
+            .CompareOperation(comparison, r0)
             .Return();
 
         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1472,15 +1304,12 @@
         HandleAndZoneScope handles;
         i::Factory* factory = handles.main_isolate()->factory();
         BytecodeArrayBuilder builder(handles.main_isolate(),
-                                     handles.main_zone());
+                                     handles.main_zone(), 0, 0, 1);
         Register r0(0);
-        builder.set_locals_count(1);
-        builder.set_context_count(0);
-        builder.set_parameter_count(0);
         builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs))
             .StoreAccumulatorInRegister(r0)
             .LoadLiteral(factory->NewStringFromAsciiChecked(rhs))
-            .CompareOperation(comparison, r0, Strength::WEAK)
+            .CompareOperation(comparison, r0)
             .Return();
 
         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1519,24 +1348,21 @@
           HandleAndZoneScope handles;
           i::Factory* factory = handles.main_isolate()->factory();
           BytecodeArrayBuilder builder(handles.main_isolate(),
-                                       handles.main_zone());
+                                       handles.main_zone(), 0, 0, 1);
           Register r0(0);
-          builder.set_locals_count(1);
-          builder.set_context_count(0);
-          builder.set_parameter_count(0);
           if (pass == 0) {
             // Comparison with HeapNumber on the lhs and String on the rhs
             builder.LoadLiteral(factory->NewNumber(lhs))
                 .StoreAccumulatorInRegister(r0)
                 .LoadLiteral(factory->NewStringFromAsciiChecked(rhs_cstr))
-                .CompareOperation(comparison, r0, Strength::WEAK)
+                .CompareOperation(comparison, r0)
                 .Return();
           } else {
             // Comparison with HeapNumber on the rhs and String on the lhs
             builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs_cstr))
                 .StoreAccumulatorInRegister(r0)
                 .LoadLiteral(factory->NewNumber(rhs))
-                .CompareOperation(comparison, r0, Strength::WEAK)
+                .CompareOperation(comparison, r0)
                 .Return();
           }
 
@@ -1564,15 +1390,13 @@
   Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other};
   for (size_t i = 0; i < arraysize(cases); i++) {
     bool expected_value = (i == 0);
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+                                 0, 1);
     Register r0(0);
-    builder.set_locals_count(1);
-    builder.set_context_count(0);
-    builder.set_parameter_count(0);
     builder.LoadLiteral(cases[i]);
     builder.StoreAccumulatorInRegister(r0)
         .LoadLiteral(func)
-        .CompareOperation(Token::Value::INSTANCEOF, r0, Strength::WEAK)
+        .CompareOperation(Token::Value::INSTANCEOF, r0)
         .Return();
 
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1590,20 +1414,18 @@
   i::Factory* factory = handles.main_isolate()->factory();
   // Allocate an array
   Handle<i::JSArray> array =
-      factory->NewJSArray(i::ElementsKind::FAST_SMI_ELEMENTS);
+      factory->NewJSArray(0, i::ElementsKind::FAST_SMI_ELEMENTS);
   // Check for these properties on the array object
   const char* properties[] = {"length", "fuzzle", "x", "0"};
   for (size_t i = 0; i < arraysize(properties); i++) {
     bool expected_value = (i == 0);
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+                                 0, 1);
     Register r0(0);
-    builder.set_locals_count(1);
-    builder.set_context_count(0);
-    builder.set_parameter_count(0);
     builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i]))
         .StoreAccumulatorInRegister(r0)
         .LoadLiteral(Handle<Object>::cast(array))
-        .CompareOperation(Token::Value::IN, r0, Strength::WEAK)
+        .CompareOperation(Token::Value::IN, r0)
         .Return();
 
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1620,11 +1442,9 @@
   HandleAndZoneScope handles;
   for (size_t i = 1; i < 10; i++) {
     bool expected_value = ((i & 1) == 1);
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+                                 0, 0);
     Register r0(0);
-    builder.set_locals_count(0);
-    builder.set_context_count(0);
-    builder.set_parameter_count(0);
     builder.LoadFalse();
     for (size_t j = 0; j < i; j++) {
       builder.LogicalNot();
@@ -1683,11 +1503,9 @@
   };
 
   for (size_t i = 0; i < arraysize(object_type_tuples); i++) {
-    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+                                 0, 0);
     Register r0(0);
-    builder.set_locals_count(0);
-    builder.set_context_count(0);
-    builder.set_parameter_count(0);
     LoadAny(&builder, factory, object_type_tuples[i].first);
     builder.LogicalNot();
     builder.Return();
@@ -1731,10 +1549,8 @@
 TEST(InterpreterCallRuntime) {
   HandleAndZoneScope handles;
 
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(2);
-  builder.set_context_count(0);
-  builder.set_parameter_count(1);
+  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+                               0, 2);
   builder.LoadLiteral(Smi::FromInt(15))
       .StoreAccumulatorInRegister(Register(0))
       .LoadLiteral(Smi::FromInt(40))
@@ -2133,29 +1949,76 @@
 
 TEST(InterpreterTryCatch) {
   HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
 
-  // TODO(rmcilroy): modify tests when we have real try catch support.
-  std::string source(InterpreterTester::SourceForBody(
-      "var a = 1; try { a = a + 1; } catch(e) { a = a + 2; }; return a;"));
-  InterpreterTester tester(handles.main_isolate(), source.c_str());
-  auto callable = tester.GetCallable<>();
+  std::pair<const char*, Handle<Object>> catches[] = {
+      std::make_pair("var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
+                     handle(Smi::FromInt(2), isolate)),
+      std::make_pair("var a; try { undef.x } catch(e) { a = 2 }; return a;",
+                     handle(Smi::FromInt(2), isolate)),
+      std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
+                     handle(Smi::FromInt(3), isolate)),
+      std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 };"
+                     "       try { throw a } catch(e) { a = e + 3 }; return a;",
+                     handle(Smi::FromInt(6), isolate)),
+  };
 
-  Handle<Object> return_val = callable().ToHandleChecked();
-  CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(2));
+  for (size_t i = 0; i < arraysize(catches); i++) {
+    std::string source(InterpreterTester::SourceForBody(catches[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(*catches[i].second));
+  }
 }
 
 
 TEST(InterpreterTryFinally) {
   HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  i::Factory* factory = isolate->factory();
 
-  // TODO(rmcilroy): modify tests when we have real try finally support.
-  std::string source(InterpreterTester::SourceForBody(
-      "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;"));
-  InterpreterTester tester(handles.main_isolate(), source.c_str());
-  auto callable = tester.GetCallable<>();
+  std::pair<const char*, Handle<Object>> finallies[] = {
+      std::make_pair(
+          "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
+          factory->NewStringFromStaticChars("R4")),
+      std::make_pair(
+          "var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
+          factory->NewStringFromStaticChars("R23")),
+      std::make_pair(
+          "var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
+          factory->NewStringFromStaticChars("E23")),
+      std::make_pair(
+          "var a = 1; try { a = 2; throw 23; } finally { return a; };",
+          factory->NewStringFromStaticChars("R2")),
+      std::make_pair(
+          "var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
+          factory->NewStringFromStaticChars("E42")),
+      std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
+                     "  try { a = 2; break; } finally { a = 3; }"
+                     "} return a + i;",
+                     factory->NewStringFromStaticChars("R13")),
+      std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
+                     "  try { a = 2; continue; } finally { a = 3; }"
+                     "} return a + i;",
+                     factory->NewStringFromStaticChars("R23")),
+      std::make_pair("var a = 1; try { a = 2;"
+                     "  try { a = 3; throw 23; } finally { a = 4; }"
+                     "} catch(e) { a = a + e; } return a;",
+                     factory->NewStringFromStaticChars("R27")),
+  };
 
-  Handle<Object> return_val = callable().ToHandleChecked();
-  CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(4));
+  const char* try_wrapper =
+      "(function() { try { return 'R' + f() } catch(e) { return 'E' + e }})()";
+
+  for (size_t i = 0; i < arraysize(finallies); i++) {
+    std::string source(InterpreterTester::SourceForBody(finallies[i].first));
+    InterpreterTester tester(handles.main_isolate(), source.c_str());
+    tester.GetCallable<>();
+    Handle<Object> wrapped = v8::Utils::OpenHandle(*CompileRun(try_wrapper));
+    CHECK(wrapped->SameValue(*finallies[i].second));
+  }
 }
 
 
@@ -2164,7 +2027,6 @@
   i::Isolate* isolate = handles.main_isolate();
   i::Factory* factory = isolate->factory();
 
-  // TODO(rmcilroy): modify tests when we have real try catch support.
   std::pair<const char*, Handle<Object>> throws[] = {
       std::make_pair("throw undefined;\n",
                      factory->undefined_value()),
@@ -2364,6 +2226,15 @@
       std::make_pair("function f(a, b, c, d) {"
                      "  'use strict'; c = b; return arguments[2]; }",
                      2),
+      // check rest parameters
+      std::make_pair("function f(...restArray) { return restArray[0]; }", 0),
+      std::make_pair("function f(a, ...restArray) { return restArray[0]; }", 1),
+      std::make_pair("function f(a, ...restArray) { return arguments[0]; }", 0),
+      std::make_pair("function f(a, ...restArray) { return arguments[1]; }", 1),
+      std::make_pair("function f(a, ...restArray) { return restArray[1]; }", 2),
+      std::make_pair("function f(a, ...arguments) { return arguments[0]; }", 1),
+      std::make_pair("function f(a, b, ...restArray) { return restArray[0]; }",
+                     2),
   };
 
   // Test passing no arguments.
@@ -2698,211 +2569,301 @@
 
 
 TEST(InterpreterForIn) {
-  HandleAndZoneScope handles;
-
   std::pair<const char*, int> for_in_samples[] = {
-      {"function f() {\n"
-       "  var r = -1;\n"
-       "  for (var a in null) { r = a; }\n"
-       "  return r;\n"
-       "}",
+      {"var r = -1;\n"
+       "for (var a in null) { r = a; }\n"
+       "return r;\n",
        -1},
-      {"function f() {\n"
-       "  var r = -1;\n"
-       "  for (var a in undefined) { r = a; }\n"
-       "  return r;\n"
-       "}",
+      {"var r = -1;\n"
+       "for (var a in undefined) { r = a; }\n"
+       "return r;\n",
        -1},
-      {"function f() {\n"
-       "  var r = 0;\n"
-       "  for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
-       "  return r;\n"
-       "}",
+      {"var r = 0;\n"
+       "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
+       "return r;\n",
        0xf},
-      {"function f() {\n"
-       "  var r = 0;\n"
-       "  for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
-       "  var r = 0;\n"
-       "  for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
-       "  return r;\n"
-       "}",
-       0xf},
-      {"function f() {\n"
-       "  var r = 0;\n"
-       "  for (var a in 'foobar') { r = r + (1 << a); }\n"
-       "  return r;\n"
-       "}",
-       0x3f},
-      {"function f() {\n"
-       "  var r = 0;\n"
-       "  for (var a in {1:0, 10:1, 100:2, 1000:3}) {\n"
-       "    r = r + Number(a);\n"
-       "   }\n"
-       "   return r;\n"
-       "}",
-       1111},
-      {"function f() {\n"
-       "  var r = 0;\n"
-       "  var data = {1:0, 10:1, 100:2, 1000:3};\n"
-       "  for (var a in data) {\n"
-       "    if (a == 1) delete data[1];\n"
-       "    r = r + Number(a);\n"
-       "   }\n"
-       "   return r;\n"
-       "}",
-       1111},
-      {"function f() {\n"
-       "  var r = 0;\n"
-       "  var data = {1:0, 10:1, 100:2, 1000:3};\n"
-       "  for (var a in data) {\n"
-       "    if (a == 10) delete data[100];\n"
-       "    r = r + Number(a);\n"
-       "   }\n"
-       "   return r;\n"
-       "}",
-       1011},
-      {"function f() {\n"
-       "  var r = 0;\n"
-       "  var data = {1:0, 10:1, 100:2, 1000:3};\n"
-       "  for (var a in data) {\n"
-       "    if (a == 10) data[10000] = 4;\n"
-       "    r = r + Number(a);\n"
-       "   }\n"
-       "   return r;\n"
-       "}",
-       1111},
-      {"function f() {\n"
-       "  var r = 0;\n"
-       "  var input = 'foobar';\n"
-       "  for (var a in input) {\n"
-       "    if (input[a] == 'b') break;\n"
-       "    r = r + (1 << a);\n"
-       "  }\n"
-       "  return r;\n"
-       "}",
-       0x7},
-      {"function f() {\n"
+      {"var r = 0;\n"
+       "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
        "var r = 0;\n"
+       "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
+       "return r;\n",
+       0xf},
+      {"var r = 0;\n"
+       "for (var a in 'foobar') { r = r + (1 << a); }\n"
+       "return r;\n",
+       0x3f},
+      {"var r = 0;\n"
+       "for (var a in {1:0, 10:1, 100:2, 1000:3}) {\n"
+       "  r = r + Number(a);\n"
+       " }\n"
+       " return r;\n",
+       1111},
+      {"var r = 0;\n"
+       "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+       "for (var a in data) {\n"
+       "  if (a == 1) delete data[1];\n"
+       "  r = r + Number(a);\n"
+       " }\n"
+       " return r;\n",
+       1111},
+      {"var r = 0;\n"
+       "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+       "for (var a in data) {\n"
+       "  if (a == 10) delete data[100];\n"
+       "  r = r + Number(a);\n"
+       " }\n"
+       " return r;\n",
+       1011},
+      {"var r = 0;\n"
+       "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+       "for (var a in data) {\n"
+       "  if (a == 10) data[10000] = 4;\n"
+       "  r = r + Number(a);\n"
+       " }\n"
+       " return r;\n",
+       1111},
+      {"var r = 0;\n"
        "var input = 'foobar';\n"
        "for (var a in input) {\n"
-       "   if (input[a] == 'b') continue;\n"
-       "   r = r + (1 << a);\n"
+       "  if (input[a] == 'b') break;\n"
+       "  r = r + (1 << a);\n"
        "}\n"
-       "return r;\n"
-       "}",
+       "return r;\n",
+       0x7},
+      {"var r = 0;\n"
+       "var input = 'foobar';\n"
+       "for (var a in input) {\n"
+       " if (input[a] == 'b') continue;\n"
+       " r = r + (1 << a);\n"
+       "}\n"
+       "return r;\n",
        0x37},
+      {"var r = 0;\n"
+       "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+       "for (var a in data) {\n"
+       "  if (a == 10) {\n"
+       "     data[10000] = 4;\n"
+       "  }\n"
+       "  r = r + Number(a);\n"
+       "}\n"
+       "return r;\n",
+       1111},
+      {"var r = [ 3 ];\n"
+       "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+       "for (r[10] in data) {\n"
+       "}\n"
+       "return Number(r[10]);\n",
+       1000},
+      {"var r = [ 3 ];\n"
+       "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+       "for (r['100'] in data) {\n"
+       "}\n"
+       "return Number(r['100']);\n",
+       1000},
+      {"var obj = {}\n"
+       "var descObj = new Boolean(false);\n"
+       "var accessed = 0;\n"
+       "descObj.enumerable = true;\n"
+       "Object.defineProperties(obj, { prop:descObj });\n"
+       "for (var p in obj) {\n"
+       "  if (p === 'prop') { accessed = 1; }\n"
+       "}\n"
+       "return accessed;",
+       1},
+      {"var appointment = {};\n"
+       "Object.defineProperty(appointment, 'startTime', {\n"
+       "    value: 1001,\n"
+       "    writable: false,\n"
+       "    enumerable: false,\n"
+       "    configurable: true\n"
+       "});\n"
+       "Object.defineProperty(appointment, 'name', {\n"
+       "    value: 'NAME',\n"
+       "    writable: false,\n"
+       "    enumerable: false,\n"
+       "    configurable: true\n"
+       "});\n"
+       "var meeting = Object.create(appointment);\n"
+       "Object.defineProperty(meeting, 'conferenceCall', {\n"
+       "    value: 'In-person meeting',\n"
+       "    writable: false,\n"
+       "    enumerable: false,\n"
+       "    configurable: true\n"
+       "});\n"
+       "\n"
+       "var teamMeeting = Object.create(meeting);\n"
+       "\n"
+       "var flags = 0;\n"
+       "for (var p in teamMeeting) {\n"
+       "    if (p === 'startTime') {\n"
+       "        flags |= 1;\n"
+       "    }\n"
+       "    if (p === 'name') {\n"
+       "        flags |= 2;\n"
+       "    }\n"
+       "    if (p === 'conferenceCall') {\n"
+       "        flags |= 4;\n"
+       "    }\n"
+       "}\n"
+       "\n"
+       "var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n"
+       "    !teamMeeting.hasOwnProperty('startTime') &&\n"
+       "    !teamMeeting.hasOwnProperty('conferenceCall');\n"
+       "if (!hasOwnProperty) {\n"
+       "    flags |= 8;\n"
+       "}\n"
+       "return flags;\n",
+       0},
+      {"var data = {x:23, y:34};\n"
+       " var result = 0;\n"
+       "var o = {};\n"
+       "var arr = [o];\n"
+       "for (arr[0].p in data)\n"       // This is to test if value is loaded
+       "  result += data[arr[0].p];\n"  // back from accumulator before storing
+       "return result;\n",              // named properties.
+       57},
+      {"var data = {x:23, y:34};\n"
+       "var result = 0;\n"
+       "var o = {};\n"
+       "var i = 0;\n"
+       "for (o[i++] in data)\n"       // This is to test if value is loaded
+       "  result += data[o[i-1]];\n"  // back from accumulator before
+       "return result;\n",            // storing keyed properties.
+       57}};
+
+  // Two passes are made for this test. On the first, 8-bit register
+  // operands are employed, and on the 16-bit register operands are
+  // used.
+  for (int pass = 0; pass < 2; pass++) {
+    HandleAndZoneScope handles;
+    std::ostringstream wide_os;
+    if (pass == 1) {
+      for (int i = 0; i < 200; i++) {
+        wide_os << "var local" << i << " = 0;\n";
+      }
+    }
+
+    for (size_t i = 0; i < arraysize(for_in_samples); i++) {
+      std::ostringstream body_os;
+      body_os << wide_os.str() << for_in_samples[i].first;
+      std::string body(body_os.str());
+      std::string function = InterpreterTester::SourceForBody(body.c_str());
+      InterpreterTester tester(handles.main_isolate(), function.c_str());
+      auto callable = tester.GetCallable<>();
+      Handle<Object> return_val = callable().ToHandleChecked();
+      CHECK_EQ(Handle<Smi>::cast(return_val)->value(),
+               for_in_samples[i].second);
+    }
+  }
+}
+
+
+TEST(InterpreterForOf) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  i::Factory* factory = isolate->factory();
+
+  std::pair<const char*, Handle<Object>> for_of[] = {
       {"function f() {\n"
        "  var r = 0;\n"
-       "  var data = {1:0, 10:1, 100:2, 1000:3};\n"
-       "  for (var a in data) {\n"
-       "    if (a == 10) {\n"
-       "       data[10000] = 4;\n"
-       "    }\n"
-       "    r = r + Number(a);\n"
+       "  for (var a of [0,6,7,9]) { r += a; }\n"
+       "  return r;\n"
+       "}",
+       handle(Smi::FromInt(22), isolate)},
+      {"function f() {\n"
+       "  var r = '';\n"
+       "  for (var a of 'foobar') { r = a + r; }\n"
+       "  return r;\n"
+       "}",
+       factory->NewStringFromStaticChars("raboof")},
+      {"function f() {\n"
+       "  var a = [1, 2, 3];\n"
+       "  a.name = 4;\n"
+       "  var r = 0;\n"
+       "  for (var x of a) { r += x; }\n"
+       "  return r;\n"
+       "}",
+       handle(Smi::FromInt(6), isolate)},
+      {"function f() {\n"
+       "  var r = '';\n"
+       "  var data = [1, 2, 3]; \n"
+       "  for (a of data) { delete data[0]; r += a; } return r; }",
+       factory->NewStringFromStaticChars("123")},
+      {"function f() {\n"
+       "  var r = '';\n"
+       "  var data = [1, 2, 3]; \n"
+       "  for (a of data) { delete data[2]; r += a; } return r; }",
+       factory->NewStringFromStaticChars("12undefined")},
+      {"function f() {\n"
+       "  var r = '';\n"
+       "  var data = [1, 2, 3]; \n"
+       "  for (a of data) { delete data; r += a; } return r; }",
+       factory->NewStringFromStaticChars("123")},
+      {"function f() {\n"
+       "  var r = '';\n"
+       "  var input = 'foobar';\n"
+       "  for (var a of input) {\n"
+       "    if (a == 'b') break;\n"
+       "    r += a;\n"
        "  }\n"
        "  return r;\n"
        "}",
-       1111},
+       factory->NewStringFromStaticChars("foo")},
       {"function f() {\n"
-       "  var r = [ 3 ];\n"
-       "  var data = {1:0, 10:1, 100:2, 1000:3};\n"
-       "  for (r[10] in data) {\n"
+       "  var r = '';\n"
+       "  var input = 'foobar';\n"
+       "  for (var a of input) {\n"
+       "    if (a == 'b') continue;\n"
+       "    r += a;\n"
        "  }\n"
-       "  return Number(r[10]);\n"
+       "  return r;\n"
        "}",
-       1000},
+       factory->NewStringFromStaticChars("fooar")},
       {"function f() {\n"
-       "  var r = [ 3 ];\n"
-       "  var data = {1:0, 10:1, 100:2, 1000:3};\n"
-       "  for (r['100'] in data) {\n"
-       "  }\n"
-       "  return Number(r['100']);\n"
+       "  var r = '';\n"
+       "  var data = [1, 2, 3, 4]; \n"
+       "  for (a of data) { data[2] = 567; r += a; }\n"
+       "  return r;\n"
        "}",
-       1000},
+       factory->NewStringFromStaticChars("125674")},
       {"function f() {\n"
-       "  var obj = {}\n"
-       "  var descObj = new Boolean(false);\n"
-       "  var accessed = 0;\n"
-       "  descObj.enumerable = true;\n"
-       "  Object.defineProperties(obj, { prop:descObj });\n"
-       "  for (var p in obj) {\n"
-       "    if (p === 'prop') { accessed = 1; }\n"
-       "  }\n"
-       "  return accessed;"
+       "  var r = '';\n"
+       "  var data = [1, 2, 3, 4]; \n"
+       "  for (a of data) { data[4] = 567; r += a; }\n"
+       "  return r;\n"
        "}",
-       1},
+       factory->NewStringFromStaticChars("1234567")},
       {"function f() {\n"
-       "  var appointment = {};\n"
-       "  Object.defineProperty(appointment, 'startTime', {\n"
-       "      value: 1001,\n"
-       "      writable: false,\n"
-       "      enumerable: false,\n"
-       "      configurable: true\n"
-       "  });\n"
-       "  Object.defineProperty(appointment, 'name', {\n"
-       "      value: 'NAME',\n"
-       "      writable: false,\n"
-       "      enumerable: false,\n"
-       "      configurable: true\n"
-       "  });\n"
-       "  var meeting = Object.create(appointment);\n"
-       "  Object.defineProperty(meeting, 'conferenceCall', {\n"
-       "      value: 'In-person meeting',\n"
-       "      writable: false,\n"
-       "      enumerable: false,\n"
-       "      configurable: true\n"
-       "  });\n"
-       "\n"
-       "  var teamMeeting = Object.create(meeting);\n"
-       "\n"
-       "  var flags = 0;\n"
-       "  for (var p in teamMeeting) {\n"
-       "      if (p === 'startTime') {\n"
-       "          flags |= 1;\n"
+       "  var r = '';\n"
+       "  var data = [1, 2, 3, 4]; \n"
+       "  for (a of data) { data[5] = 567; r += a; }\n"
+       "  return r;\n"
+       "}",
+       factory->NewStringFromStaticChars("1234undefined567")},
+      {"function f() {\n"
+       "  var r = '';\n"
+       "  var obj = new Object();\n"
+       "  obj[Symbol.iterator] = function() { return {\n"
+       "    index: 3,\n"
+       "    data: ['a', 'b', 'c', 'd'],"
+       "    next: function() {"
+       "      return {"
+       "        done: this.index == -1,\n"
+       "        value: this.index < 0 ? undefined : this.data[this.index--]\n"
        "      }\n"
-       "      if (p === 'name') {\n"
-       "          flags |= 2;\n"
-       "      }\n"
-       "      if (p === 'conferenceCall') {\n"
-       "          flags |= 4;\n"
-       "      }\n"
-       "  }\n"
-       "\n"
-       "  var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n"
-       "      !teamMeeting.hasOwnProperty('startTime') &&\n"
-       "      !teamMeeting.hasOwnProperty('conferenceCall');\n"
-       "  if (!hasOwnProperty) {\n"
-       "      flags |= 8;\n"
-       "  }\n"
-       "  return flags;\n"
-       "  }",
-       0},
-      {"function f() {\n"
-       " var data = {x:23, y:34};\n"
-       " var result = 0;\n"
-       " var o = {};\n"
-       " var arr = [o];\n"
-       " for (arr[0].p in data)\n"      // This is to test if value is loaded
-       "  result += data[arr[0].p];\n"  // back from accumulator before storing
-       " return result;\n"              // named properties.
+       "    }\n"
+       "    }}\n"
+       "  for (a of obj) { r += a }\n"
+       "  return r;\n"
        "}",
-       57},
-      {"function f() {\n"
-       " var data = {x:23, y:34};\n"
-       " var result = 0;\n"
-       " var o = {};\n"
-       " var i = 0;\n"
-       " for (o[i++] in data)\n"      // This is to test if value is loaded
-       "  result += data[o[i-1]];\n"  // back from accumulator before
-       " return result;\n"            // storing keyed properties.
-       "}",
-       57}};
+       factory->NewStringFromStaticChars("dcba")},
+  };
 
-  for (size_t i = 0; i < arraysize(for_in_samples); i++) {
-    InterpreterTester tester(handles.main_isolate(), for_in_samples[i].first);
+  for (size_t i = 0; i < arraysize(for_of); i++) {
+    InterpreterTester tester(handles.main_isolate(), for_of[i].first);
     auto callable = tester.GetCallable<>();
     Handle<Object> return_val = callable().ToHandleChecked();
-    CHECK_EQ(Handle<Smi>::cast(return_val)->value(), for_in_samples[i].second);
+    CHECK(return_val->SameValue(*for_of[i].second));
   }
 }
 
@@ -3422,10 +3383,10 @@
 
 TEST(JumpWithConstantsAndWideConstants) {
   HandleAndZoneScope handles;
-  auto isolate = handles.main_isolate();
-  auto factory = isolate->factory();
   const int kStep = 13;
-  for (int constants = 3; constants < 256 + 3 * kStep; constants += kStep) {
+  for (int constants = 11; constants < 256 + 3 * kStep; constants += kStep) {
+    auto isolate = handles.main_isolate();
+    auto factory = isolate->factory();
     std::ostringstream filler_os;
     // Generate a string that consumes constant pool entries and
     // spread out branch distances in script below.
@@ -3448,8 +3409,8 @@
     for (int a = 0; a < 3; a++) {
       InterpreterTester tester(handles.main_isolate(), script.c_str());
       auto callable = tester.GetCallable<Handle<Object>>();
-      Handle<Object> return_val =
-          callable(factory->NewNumberFromInt(a)).ToHandleChecked();
+      Handle<Object> argument = factory->NewNumberFromInt(a);
+      Handle<Object> return_val = callable(argument).ToHandleChecked();
       static const int results[] = {11, 12, 2};
       CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
     }
@@ -3500,7 +3461,6 @@
     std::string source(InterpreterTester::SourceForBody(eval[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(*eval[i].second));
   }
@@ -3562,6 +3522,646 @@
   }
 }
 
+
+TEST(InterpreterEvalVariableDecl) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  i::Factory* factory = isolate->factory();
+
+  std::pair<const char*, Handle<Object>> eval_global[] = {
+      {"function f() { eval('var x = 10; x++;'); return x; }",
+       handle(Smi::FromInt(11), isolate)},
+      {"function f() { var x = 20; eval('var x = 10; x++;'); return x; }",
+       handle(Smi::FromInt(11), isolate)},
+      {"function f() {"
+       " var x = 20;"
+       " eval('\"use strict\"; var x = 10; x++;');"
+       " return x; }",
+       handle(Smi::FromInt(20), isolate)},
+      {"function f() {"
+       " var y = 30;"
+       " eval('var x = {1:20}; x[2]=y;');"
+       " return x[2]; }",
+       handle(Smi::FromInt(30), isolate)},
+      {"function f() {"
+       " eval('var x = {name:\"test\"};');"
+       " return x.name; }",
+       factory->NewStringFromStaticChars("test")},
+      {"function f() {"
+       "  eval('var x = [{name:\"test\"}, {type:\"cc\"}];');"
+       "  return x[1].type+x[0].name; }",
+       factory->NewStringFromStaticChars("cctest")},
+      {"function f() {\n"
+       " var x = 3;\n"
+       " var get_eval_x;\n"
+       " eval('\"use strict\"; "
+       "      var x = 20; "
+       "      get_eval_x = function func() {return x;};');\n"
+       " return get_eval_x() + x;\n"
+       "}",
+       handle(Smi::FromInt(23), isolate)},
+      // TODO(mythria): Add tests with const declarations.
+  };
+
+  for (size_t i = 0; i < arraysize(eval_global); i++) {
+    InterpreterTester tester(handles.main_isolate(), eval_global[i].first, "*");
+    auto callable = tester.GetCallable<>();
+
+    Handle<i::Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*eval_global[i].second));
+  }
+}
+
+
+TEST(InterpreterEvalFunctionDecl) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+
+  std::pair<const char*, Handle<Object>> eval_func_decl[] = {
+      {"function f() {\n"
+       " var x = 3;\n"
+       " eval('var x = 20;"
+       "       function get_x() {return x;};');\n"
+       " return get_x() + x;\n"
+       "}",
+       handle(Smi::FromInt(40), isolate)},
+  };
+
+  for (size_t i = 0; i < arraysize(eval_func_decl); i++) {
+    InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first,
+                             "*");
+    auto callable = tester.GetCallable<>();
+
+    Handle<i::Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*eval_func_decl[i].second));
+  }
+}
+
+TEST(InterpreterWideRegisterArithmetic) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+
+  static const size_t kMaxRegisterForTest = 150;
+  std::ostringstream os;
+  os << "function " << InterpreterTester::function_name() << "(arg) {\n";
+  os << "  var retval = -77;\n";
+  for (size_t i = 0; i < kMaxRegisterForTest; i++) {
+    os << "  var x" << i << " = " << i << ";\n";
+  }
+  for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
+    size_t j = kMaxRegisterForTest - i - 1;
+    os << "  var tmp = x" << j << ";\n";
+    os << "  var x" << j << " = x" << i << ";\n";
+    os << "  var x" << i << " = tmp;\n";
+  }
+  for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
+    size_t j = kMaxRegisterForTest - i - 1;
+    os << "  var tmp = x" << j << ";\n";
+    os << "  var x" << j << " = x" << i << ";\n";
+    os << "  var x" << i << " = tmp;\n";
+  }
+  for (size_t i = 0; i < kMaxRegisterForTest; i++) {
+    os << "  if (arg == " << i << ") {\n"  //
+       << "    retval = x" << i << ";\n"   //
+       << "  }\n";                         //
+  }
+  os << "  return retval;\n";
+  os << "}\n";
+
+  std::string source = os.str();
+  InterpreterTester tester(handles.main_isolate(), source.c_str());
+  auto callable = tester.GetCallable<Handle<Object>>();
+  for (size_t i = 0; i < kMaxRegisterForTest; i++) {
+    Handle<Object> arg = handle(Smi::FromInt(static_cast<int>(i)), isolate);
+    Handle<Object> return_value = callable(arg).ToHandleChecked();
+    CHECK(return_value->SameValue(*arg));
+  }
+}
+
+TEST(InterpreterCallWideRegisters) {
+  static const int kPeriod = 25;
+  static const int kLength = 512;
+  static const int kStartChar = 65;
+
+  for (int pass = 0; pass < 3; pass += 1) {
+    std::ostringstream os;
+    for (int i = 0; i < pass * 97; i += 1) {
+      os << "var x" << i << " = " << i << "\n";
+    }
+    os << "return String.fromCharCode(";
+    os << kStartChar;
+    for (int i = 1; i < kLength; i += 1) {
+      os << "," << kStartChar + (i % kPeriod);
+    }
+    os << ");";
+    std::string source = InterpreterTester::SourceForBody(os.str().c_str());
+    HandleAndZoneScope handles;
+    InterpreterTester tester(handles.main_isolate(), source.c_str());
+    auto callable = tester.GetCallable();
+    Handle<Object> return_val = callable().ToHandleChecked();
+    Handle<String> return_string = Handle<String>::cast(return_val);
+    CHECK_EQ(return_string->length(), kLength);
+    for (int i = 0; i < kLength; i += 1) {
+      CHECK_EQ(return_string->Get(i), 65 + (i % kPeriod));
+    }
+  }
+}
+
+TEST(InterpreterWideParametersPickOne) {
+  static const int kParameterCount = 130;
+  for (int parameter = 0; parameter < 10; parameter++) {
+    HandleAndZoneScope handles;
+    i::Isolate* isolate = handles.main_isolate();
+    std::ostringstream os;
+    os << "function " << InterpreterTester::function_name() << "(arg) {\n";
+    os << "  function selector(i";
+    for (int i = 0; i < kParameterCount; i++) {
+      os << ","
+         << "a" << i;
+    }
+    os << ") {\n";
+    os << "  return a" << parameter << ";\n";
+    os << "  };\n";
+    os << "  return selector(arg";
+    for (int i = 0; i < kParameterCount; i++) {
+      os << "," << i;
+    }
+    os << ");";
+    os << "}\n";
+
+    std::string source = os.str();
+    InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
+    auto callable = tester.GetCallable<Handle<Object>>();
+    Handle<Object> arg = handle(Smi::FromInt(0xaa55), isolate);
+    Handle<Object> return_value = callable(arg).ToHandleChecked();
+    Handle<Smi> actual = Handle<Smi>::cast(return_value);
+    CHECK_EQ(actual->value(), parameter);
+  }
+}
+
+TEST(InterpreterWideParametersSummation) {
+  static int kParameterCount = 200;
+  static int kBaseValue = 17000;
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  std::ostringstream os;
+  os << "function " << InterpreterTester::function_name() << "(arg) {\n";
+  os << "  function summation(i";
+  for (int i = 0; i < kParameterCount; i++) {
+    os << ","
+       << "a" << i;
+  }
+  os << ") {\n";
+  os << "    var sum = " << kBaseValue << ";\n";
+  os << "    switch(i) {\n";
+  for (int i = 0; i < kParameterCount; i++) {
+    int j = kParameterCount - i - 1;
+    os << "      case " << j << ": sum += a" << j << ";\n";
+  }
+  os << "  }\n";
+  os << "    return sum;\n";
+  os << "  };\n";
+  os << "  return summation(arg";
+  for (int i = 0; i < kParameterCount; i++) {
+    os << "," << i;
+  }
+  os << ");";
+  os << "}\n";
+
+  std::string source = os.str();
+  InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
+  auto callable = tester.GetCallable<Handle<Object>>();
+  for (int i = 0; i < kParameterCount; i++) {
+    Handle<Object> arg = handle(Smi::FromInt(i), isolate);
+    Handle<Object> return_value = callable(arg).ToHandleChecked();
+    int expected = kBaseValue + i * (i + 1) / 2;
+    Handle<Smi> actual = Handle<Smi>::cast(return_value);
+    CHECK_EQ(actual->value(), expected);
+  }
+}
+
+TEST(InterpreterDoExpression) {
+  bool old_flag = FLAG_harmony_do_expressions;
+  FLAG_harmony_do_expressions = true;
+
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  Factory* factory = isolate->factory();
+
+  std::pair<const char*, Handle<Object>> do_expr[] = {
+      {"var a = do {}; return a;", factory->undefined_value()},
+      {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
+      {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
+      {"var a = do { var x = 100; x++; }; return a;",
+       handle(Smi::FromInt(100), isolate)},
+      {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
+       "return i;",
+       handle(Smi::FromInt(3), isolate)},
+  };
+
+  for (size_t i = 0; i < arraysize(do_expr); i++) {
+    std::string source(InterpreterTester::SourceForBody(do_expr[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(*do_expr[i].second));
+  }
+
+  FLAG_harmony_do_expressions = old_flag;
+}
+
+TEST(InterpreterWithStatement) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+
+  std::pair<const char*, Handle<Object>> with_stmt[] = {
+      {"with({x:42}) return x;", handle(Smi::FromInt(42), isolate)},
+      {"with({}) { var y = 10; return y;}", handle(Smi::FromInt(10), isolate)},
+      {"var y = {x:42};"
+       " function inner() {"
+       "   var x = 20;"
+       "   with(y) return x;"
+       "}"
+       "return inner();",
+       handle(Smi::FromInt(42), isolate)},
+      {"var y = {x:42};"
+       " function inner(o) {"
+       "   var x = 20;"
+       "   with(o) return x;"
+       "}"
+       "return inner(y);",
+       handle(Smi::FromInt(42), isolate)},
+  };
+
+  for (size_t i = 0; i < arraysize(with_stmt); i++) {
+    std::string source(InterpreterTester::SourceForBody(with_stmt[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(*with_stmt[i].second));
+  }
+}
+
+TEST(InterpreterClassLiterals) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  std::pair<const char*, Handle<Object>> examples[] = {
+      {"class C {\n"
+       "  constructor(x) { this.x_ = x; }\n"
+       "  method() { return this.x_; }\n"
+       "}\n"
+       "return new C(99).method();",
+       handle(Smi::FromInt(99), isolate)},
+      {"class C {\n"
+       "  constructor(x) { this.x_ = x; }\n"
+       "  static static_method(x) { return x; }\n"
+       "}\n"
+       "return C.static_method(101);",
+       handle(Smi::FromInt(101), isolate)},
+      {"class C {\n"
+       "  get x() { return 102; }\n"
+       "}\n"
+       "return new C().x",
+       handle(Smi::FromInt(102), isolate)},
+      {"class C {\n"
+       "  static get x() { return 103; }\n"
+       "}\n"
+       "return C.x",
+       handle(Smi::FromInt(103), isolate)},
+      {"class C {\n"
+       "  constructor() { this.x_ = 0; }"
+       "  set x(value) { this.x_ = value; }\n"
+       "  get x() { return this.x_; }\n"
+       "}\n"
+       "var c = new C();"
+       "c.x = 104;"
+       "return c.x;",
+       handle(Smi::FromInt(104), isolate)},
+      {"var x = 0;"
+       "class C {\n"
+       "  static set x(value) { x = value; }\n"
+       "  static get x() { return x; }\n"
+       "}\n"
+       "C.x = 105;"
+       "return C.x;",
+       handle(Smi::FromInt(105), isolate)},
+      {"var method = 'f';"
+       "class C {\n"
+       "  [method]() { return 106; }\n"
+       "}\n"
+       "return new C().f();",
+       handle(Smi::FromInt(106), isolate)},
+  };
+
+  for (size_t i = 0; i < arraysize(examples); ++i) {
+    std::string source(InterpreterTester::SourceForBody(examples[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(*examples[i].second));
+  }
+}
+
+TEST(InterpreterClassAndSuperClass) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  std::pair<const char*, Handle<Object>> examples[] = {
+      {"class A {\n"
+       "  constructor(x) { this.x_ = x; }\n"
+       "  method() { return this.x_; }\n"
+       "}\n"
+       "class B extends A {\n"
+       "   constructor(x, y) { super(x); this.y_ = y; }\n"
+       "   method() { return super.method() + 1; }\n"
+       "}\n"
+       "return new B(998, 0).method();\n",
+       handle(Smi::FromInt(999), isolate)},
+      {"class A {\n"
+       "  constructor() { this.x_ = 2; this.y_ = 3; }\n"
+       "}\n"
+       "class B extends A {\n"
+       "  constructor() { super(); }"
+       "  method() { this.x_++; this.y_++; return this.x_ + this.y_; }\n"
+       "}\n"
+       "return new B().method();\n",
+       handle(Smi::FromInt(7), isolate)},
+      {"var calls = 0;\n"
+       "class B {}\n"
+       "B.prototype.x = 42;\n"
+       "class C extends B {\n"
+       "  constructor() {\n"
+       "    super();\n"
+       "    calls++;\n"
+       "  }\n"
+       "}\n"
+       "new C;\n"
+       "return calls;\n",
+       handle(Smi::FromInt(1), isolate)},
+      {"class A {\n"
+       "  method() { return 1; }\n"
+       "  get x() { return 2; }\n"
+       "}\n"
+       "class B extends A {\n"
+       "  method() { return super.x === 2 ? super.method() : -1; }\n"
+       "}\n"
+       "return new B().method();\n",
+       handle(Smi::FromInt(1), isolate)},
+      {"var object = { setY(v) { super.y = v; }};\n"
+       "object.setY(10);\n"
+       "return object.y;\n",
+       handle(Smi::FromInt(10), isolate)},
+  };
+
+  for (size_t i = 0; i < arraysize(examples); ++i) {
+    std::string source(InterpreterTester::SourceForBody(examples[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(*examples[i].second));
+  }
+}
+
+TEST(InterpreterConstDeclaration) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  i::Factory* factory = isolate->factory();
+
+  std::pair<const char*, Handle<Object>> const_decl[] = {
+      {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)},
+      {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)},
+      {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
+      {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
+      {"let x; return x;", factory->undefined_value()},
+      {"var x = 10; { let x = 30; } return x;",
+       handle(Smi::FromInt(10), isolate)},
+      {"let x = 10; { let x = 20; } return x;",
+       handle(Smi::FromInt(10), isolate)},
+      {"var x = 10; eval('let x = 20;'); return x;",
+       handle(Smi::FromInt(10), isolate)},
+      {"var x = 10; eval('const x = 20;'); return x;",
+       handle(Smi::FromInt(10), isolate)},
+      {"var x = 10; { const x = 20; } return x;",
+       handle(Smi::FromInt(10), isolate)},
+      {"var x = 10; { const x = 20; return x;} return -1;",
+       handle(Smi::FromInt(20), isolate)},
+      {"var a = 10;\n"
+       "for (var i = 0; i < 10; ++i) {\n"
+       " const x = i;\n"  // const declarations are block scoped.
+       " a = a + x;\n"
+       "}\n"
+       "return a;\n",
+       handle(Smi::FromInt(55), isolate)},
+  };
+
+  // Tests for sloppy mode.
+  for (size_t i = 0; i < arraysize(const_decl); i++) {
+    std::string source(InterpreterTester::SourceForBody(const_decl[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(*const_decl[i].second));
+  }
+
+  // Tests for strict mode.
+  for (size_t i = 0; i < arraysize(const_decl); i++) {
+    std::string strict_body =
+        "'use strict'; " + std::string(const_decl[i].first);
+    std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
+    InterpreterTester tester(handles.main_isolate(), source.c_str());
+    auto callable = tester.GetCallable<>();
+
+    Handle<i::Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*const_decl[i].second));
+  }
+}
+
+TEST(InterpreterConstDeclarationLookupSlots) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  i::Factory* factory = isolate->factory();
+
+  std::pair<const char*, Handle<Object>> const_decl[] = {
+      {"const x = 3; function f1() {return x;}; return x;",
+       handle(Smi::FromInt(3), isolate)},
+      {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
+       handle(Smi::FromInt(30), isolate)},
+      {"let x; x = 20; function f1() {return x;}; return x;",
+       handle(Smi::FromInt(20), isolate)},
+      {"let x; function f1() {return x;}; return x;",
+       factory->undefined_value()},
+  };
+
+  // Tests for sloppy mode.
+  for (size_t i = 0; i < arraysize(const_decl); i++) {
+    std::string source(InterpreterTester::SourceForBody(const_decl[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(*const_decl[i].second));
+  }
+
+  // Tests for strict mode.
+  for (size_t i = 0; i < arraysize(const_decl); i++) {
+    std::string strict_body =
+        "'use strict'; " + std::string(const_decl[i].first);
+    std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
+    InterpreterTester tester(handles.main_isolate(), source.c_str());
+    auto callable = tester.GetCallable<>();
+
+    Handle<i::Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*const_decl[i].second));
+  }
+}
+
+TEST(InterpreterConstInLookupContextChain) {
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+
+  const char* prologue =
+      "function OuterMost() {\n"
+      "  const outerConst = 10;\n"
+      "  let outerLet = 20;\n"
+      "  function Outer() {\n"
+      "    function Inner() {\n"
+      "      this.innerFunc = function() { ";
+  const char* epilogue =
+      "      }\n"
+      "    }\n"
+      "    this.getInnerFunc ="
+      "         function() {return new Inner().innerFunc;}\n"
+      "  }\n"
+      "  this.getOuterFunc ="
+      "     function() {return new Outer().getInnerFunc();}"
+      "}\n"
+      "var f = new OuterMost().getOuterFunc();\n"
+      "f();\n";
+  std::pair<const char*, Handle<Object>> const_decl[] = {
+      {"return outerConst;", handle(Smi::FromInt(10), isolate)},
+      {"return outerLet;", handle(Smi::FromInt(20), isolate)},
+      {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)},
+      {"var outerLet = 40; return outerLet;",
+       handle(Smi::FromInt(40), isolate)},
+      {"var outerConst = 50; return outerConst;",
+       handle(Smi::FromInt(50), isolate)},
+      {"try { outerConst = 30 } catch(e) { return -1; }",
+       handle(Smi::FromInt(-1), isolate)}};
+
+  for (size_t i = 0; i < arraysize(const_decl); i++) {
+    std::string script = std::string(prologue) +
+                         std::string(const_decl[i].first) +
+                         std::string(epilogue);
+    InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
+    auto callable = tester.GetCallable<>();
+
+    Handle<i::Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*const_decl[i].second));
+  }
+
+  // Tests for Legacy constant.
+  bool old_flag_legacy_const = FLAG_legacy_const;
+  FLAG_legacy_const = true;
+
+  std::pair<const char*, Handle<Object>> legacy_const_decl[] = {
+      {"return outerConst = 23;", handle(Smi::FromInt(23), isolate)},
+      {"outerConst = 30; return outerConst;",
+       handle(Smi::FromInt(10), isolate)},
+  };
+
+  for (size_t i = 0; i < arraysize(legacy_const_decl); i++) {
+    std::string script = std::string(prologue) +
+                         std::string(legacy_const_decl[i].first) +
+                         std::string(epilogue);
+    InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
+    auto callable = tester.GetCallable<>();
+
+    Handle<i::Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*legacy_const_decl[i].second));
+  }
+
+  FLAG_legacy_const = old_flag_legacy_const;
+}
+
+TEST(InterpreterIllegalConstDeclaration) {
+  HandleAndZoneScope handles;
+
+  std::pair<const char*, const char*> const_decl[] = {
+      {"const x = x = 10 + 3; return x;",
+       "Uncaught ReferenceError: x is not defined"},
+      {"const x = 10; x = 20; return x;",
+       "Uncaught TypeError: Assignment to constant variable."},
+      {"const x = 10; { x = 20; } return x;",
+       "Uncaught TypeError: Assignment to constant variable."},
+      {"const x = 10; eval('x = 20;'); return x;",
+       "Uncaught TypeError: Assignment to constant variable."},
+      {"let x = x + 10; return x;",
+       "Uncaught ReferenceError: x is not defined"},
+      {"'use strict'; (function f1() { f1 = 123; })() ",
+       "Uncaught TypeError: Assignment to constant variable."},
+  };
+
+  // Tests for sloppy mode.
+  for (size_t i = 0; i < arraysize(const_decl); i++) {
+    std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
+    InterpreterTester tester(handles.main_isolate(), source.c_str());
+    v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+    v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
+    CHECK(
+        message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+            .FromJust());
+  }
+
+  // Tests for strict mode.
+  for (size_t i = 0; i < arraysize(const_decl); i++) {
+    std::string strict_body =
+        "'use strict'; " + std::string(const_decl[i].first);
+    std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
+    InterpreterTester tester(handles.main_isolate(), source.c_str());
+    v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+    v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
+    CHECK(
+        message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+            .FromJust());
+  }
+}
+
+TEST(InterpreterLegacyConstDeclaration) {
+  bool old_flag_legacy_const = FLAG_legacy_const;
+  FLAG_legacy_const = true;
+
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+
+  std::pair<const char*, Handle<Object>> const_decl[] = {
+      {"const x = (x = 10) + 3; return x;", handle(Smi::FromInt(13), isolate)},
+      {"const x = 10; x = 20; return x;", handle(Smi::FromInt(10), isolate)},
+      {"var a = 10;\n"
+       "for (var i = 0; i < 10; ++i) {\n"
+       " const x = i;\n"  // Legacy constants are not block scoped.
+       " a = a + x;\n"
+       "}\n"
+       "return a;\n",
+       handle(Smi::FromInt(10), isolate)},
+      {"const x = 20; eval('x = 10;'); return x;",
+       handle(Smi::FromInt(20), isolate)},
+  };
+
+  for (size_t i = 0; i < arraysize(const_decl); i++) {
+    std::string source(InterpreterTester::SourceForBody(const_decl[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(*const_decl[i].second));
+  }
+
+  FLAG_legacy_const = old_flag_legacy_const;
+}
+
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/profiler-extension.cc b/test/cctest/profiler-extension.cc
index a917932..024cc9c 100644
--- a/test/cctest/profiler-extension.cc
+++ b/test/cctest/profiler-extension.cc
@@ -27,41 +27,35 @@
 //
 // Tests of profiles generator and utilities.
 
-#include "src/base/logging.h"
 #include "test/cctest/profiler-extension.h"
+#include "test/cctest/cctest.h"
 
 namespace v8 {
 namespace internal {
 
-
 v8::CpuProfile* ProfilerExtension::last_profile = NULL;
 const char* ProfilerExtension::kSource =
     "native function startProfiling();"
-    "native function stopProfiling();";
+    "native function stopProfiling();"
+    "native function collectSample();";
 
 v8::Local<v8::FunctionTemplate> ProfilerExtension::GetNativeFunctionTemplate(
     v8::Isolate* isolate, v8::Local<v8::String> name) {
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
-  if (name->Equals(context, v8::String::NewFromUtf8(isolate, "startProfiling",
-                                                    v8::NewStringType::kNormal)
-                                .ToLocalChecked())
-          .FromJust()) {
+  if (name->Equals(context, v8_str(isolate, "startProfiling")).FromJust()) {
     return v8::FunctionTemplate::New(isolate,
                                      ProfilerExtension::StartProfiling);
-  } else if (name->Equals(context,
-                          v8::String::NewFromUtf8(isolate, "stopProfiling",
-                                                  v8::NewStringType::kNormal)
-                              .ToLocalChecked())
-                 .FromJust()) {
-    return v8::FunctionTemplate::New(isolate,
-                                     ProfilerExtension::StopProfiling);
-  } else {
-    CHECK(false);
-    return v8::Local<v8::FunctionTemplate>();
   }
+  if (name->Equals(context, v8_str(isolate, "stopProfiling")).FromJust()) {
+    return v8::FunctionTemplate::New(isolate, ProfilerExtension::StopProfiling);
+  }
+  if (name->Equals(context, v8_str(isolate, "collectSample")).FromJust()) {
+    return v8::FunctionTemplate::New(isolate, ProfilerExtension::CollectSample);
+  }
+  CHECK(false);
+  return v8::Local<v8::FunctionTemplate>();
 }
 
-
 void ProfilerExtension::StartProfiling(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   last_profile = NULL;
@@ -71,7 +65,6 @@
       : v8::String::Empty(args.GetIsolate()));
 }
 
-
 void ProfilerExtension::StopProfiling(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   v8::CpuProfiler* cpu_profiler = args.GetIsolate()->GetCpuProfiler();
@@ -80,5 +73,10 @@
       : v8::String::Empty(args.GetIsolate()));
 }
 
+void ProfilerExtension::CollectSample(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  args.GetIsolate()->GetCpuProfiler()->CollectSample();
+}
+
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/profiler-extension.h b/test/cctest/profiler-extension.h
index e63d374..00f9a5a 100644
--- a/test/cctest/profiler-extension.h
+++ b/test/cctest/profiler-extension.h
@@ -40,10 +40,13 @@
   ProfilerExtension() : v8::Extension("v8/profiler", kSource) { }
   virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
       v8::Isolate* isolate, v8::Local<v8::String> name);
+  static v8::CpuProfile* last_profile;
+
+ private:
   static void StartProfiling(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void StopProfiling(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static v8::CpuProfile* last_profile;
- private:
+  static void CollectSample(const v8::FunctionCallbackInfo<v8::Value>& args);
+
   static const char* kSource;
 };
 
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc
index 0687c33..90ea081 100644
--- a/test/cctest/test-accessors.cc
+++ b/test/cctest/test-accessors.cc
@@ -686,9 +686,9 @@
 
 static bool security_check_value = false;
 
-
 static bool SecurityTestCallback(Local<v8::Context> accessing_context,
-                                 Local<v8::Object> accessed_object) {
+                                 Local<v8::Object> accessed_object,
+                                 Local<v8::Value> data) {
   return security_check_value;
 }
 
diff --git a/test/cctest/test-api-fast-accessor-builder.cc b/test/cctest/test-api-fast-accessor-builder.cc
index 1e1c972..eeb6b96 100644
--- a/test/cctest/test-api-fast-accessor-builder.cc
+++ b/test/cctest/test-api-fast-accessor-builder.cc
@@ -51,9 +51,9 @@
   "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
   "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
   "*/ "  // 16 lines * 64 'X' =~ 1024 character comment.
-#define FN_WARMUP(name, src)                  \
-  "function " name "() { " src INLINE_SPOILER \
-  " }; for(i = 0; i < 2; i++) { " name "() } "
+#define FN(name, src) "function " name "() { " src INLINE_SPOILER " }"
+#define WARMUP(name, count) "for(i = 0; i < " count "; i++) { " name "() } "
+#define FN_WARMUP(name, src) FN(name, src) "; " WARMUP(name, "2")
 
 static void NativePropertyAccessor(
     const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -112,6 +112,9 @@
 
 // "Fast" accessor that accesses an internal field.
 TEST(FastAccessorWithInternalField) {
+  // Crankshaft support for fast accessors is not implemented; crankshafted
+  // code uses the slow accessor which breaks this test's expectations.
+  v8::internal::FLAG_always_opt = false;
   LocalContext env;
   v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
@@ -142,6 +145,9 @@
 
 // "Fast" accessor with control flow via ...OrReturnNull methods.
 TEST(FastAccessorOrReturnNull) {
+  // Crankshaft support for fast accessors is not implemented; crankshafted
+  // code uses the slow accessor which breaks this test's expectations.
+  v8::internal::FLAG_always_opt = false;
   LocalContext env;
   v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
@@ -191,6 +197,9 @@
 
 // "Fast" accessor with simple control flow via explicit labels.
 TEST(FastAccessorControlFlowWithLabels) {
+  // Crankshaft support for fast accessors is not implemented; crankshafted
+  // code uses the slow accessor which breaks this test's expectations.
+  v8::internal::FLAG_always_opt = false;
   LocalContext env;
   v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
@@ -226,6 +235,9 @@
 
 // "Fast" accessor, loading things.
 TEST(FastAccessorLoad) {
+  // Crankshaft support for fast accessors is not implemented; crankshafted
+  // code uses the slow accessor which breaks this test's expectations.
+  v8::internal::FLAG_always_opt = false;
   LocalContext env;
   v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
@@ -286,3 +298,67 @@
   CompileRun(FN_WARMUP("loadval", "return obj.loadval"));
   ExpectString("loadval()", "Hello");
 }
+
+void ApiCallbackInt(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(12345);
+}
+
+const char* kApiCallbackStringValue =
+    "Hello World! Bizarro C++ world, actually.";
+void ApiCallbackString(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(v8_str(kApiCallbackStringValue));
+}
+
+void ApiCallbackParam(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  CHECK_EQ(1, info.Length());
+  CHECK(info[0]->IsNumber());
+  info.GetReturnValue().Set(info[0]);
+}
+
+// "Fast" accessor, callback to embedder
+TEST(FastAccessorCallback) {
+  // Crankshaft support for fast accessors is not implemented; crankshafted
+  // code uses the slow accessor which breaks this test's expectations.
+  v8::internal::FLAG_always_opt = false;
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+
+  v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
+  {
+    auto builder = v8::experimental::FastAccessorBuilder::New(isolate);
+    builder->ReturnValue(
+        builder->Call(&ApiCallbackInt, builder->IntegerConstant(999)));
+    foo->SetAccessorProperty(v8_str("int"),
+                             v8::FunctionTemplate::NewWithFastHandler(
+                                 isolate, NativePropertyAccessor, builder));
+
+    builder = v8::experimental::FastAccessorBuilder::New(isolate);
+    builder->ReturnValue(
+        builder->Call(&ApiCallbackString, builder->IntegerConstant(0)));
+    foo->SetAccessorProperty(v8_str("str"),
+                             v8::FunctionTemplate::NewWithFastHandler(
+                                 isolate, NativePropertyAccessor, builder));
+
+    builder = v8::experimental::FastAccessorBuilder::New(isolate);
+    builder->ReturnValue(
+        builder->Call(&ApiCallbackParam, builder->IntegerConstant(1000)));
+    foo->SetAccessorProperty(v8_str("param"),
+                             v8::FunctionTemplate::NewWithFastHandler(
+                                 isolate, NativePropertyAccessor, builder));
+  }
+
+  // Create an instance.
+  v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
+  CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
+
+  // Callbacks:
+  CompileRun(FN_WARMUP("callbackint", "return obj.int"));
+  ExpectInt32("callbackint()", 12345);
+
+  CompileRun(FN_WARMUP("callbackstr", "return obj.str"));
+  ExpectString("callbackstr()", kApiCallbackStringValue);
+
+  CompileRun(FN_WARMUP("callbackparam", "return obj.param"));
+  ExpectInt32("callbackparam()", 1000);
+}
diff --git a/test/cctest/test-api-interceptors.cc b/test/cctest/test-api-interceptors.cc
index 9f5eb21..ac54ede 100644
--- a/test/cctest/test-api-interceptors.cc
+++ b/test/cctest/test-api-interceptors.cc
@@ -1879,9 +1879,9 @@
   ExpectString(code, "PASSED");
 }
 
-
 static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
-                                Local<v8::Object> accessed_object) {
+                                Local<v8::Object> accessed_object,
+                                Local<v8::Value> data) {
   return false;
 }
 
@@ -3475,9 +3475,9 @@
 
 AccessCheckData* g_access_check_data = nullptr;
 
-
 bool SimpleAccessChecker(Local<v8::Context> accessing_context,
-                         Local<v8::Object> access_object) {
+                         Local<v8::Object> access_object,
+                         Local<v8::Value> data) {
   g_access_check_data->count++;
   return g_access_check_data->result;
 }
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index b78d450..f4e8fe8 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -1889,59 +1889,258 @@
 
 
 THREADED_TEST(ObjectTemplate) {
+  LocalContext env;
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
+  Local<v8::FunctionTemplate> acc =
+      v8::FunctionTemplate::New(isolate, Returns42);
+  CHECK(env->Global()
+            ->Set(env.local(), v8_str("acc"),
+                  acc->GetFunction(env.local()).ToLocalChecked())
+            .FromJust());
+
   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
   v8::Local<v8::String> class_name = v8_str("the_class_name");
   fun->SetClassName(class_name);
   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
   templ1->Set(isolate, "x", v8_num(10));
   templ1->Set(isolate, "y", v8_num(13));
-  LocalContext env;
+  templ1->Set(v8_str("foo"), acc);
   Local<v8::Object> instance1 =
       templ1->NewInstance(env.local()).ToLocalChecked();
   CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
-  CHECK(v8_compile("(p.x == 10)")
-            ->Run(env.local())
-            .ToLocalChecked()
-            ->BooleanValue(env.local())
-            .FromJust());
-  CHECK(v8_compile("(p.y == 13)")
-            ->Run(env.local())
-            .ToLocalChecked()
-            ->BooleanValue(env.local())
-            .FromJust());
+  CHECK(CompileRun("(p.x == 10)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(p.y == 13)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(p.foo == acc)")->BooleanValue(env.local()).FromJust());
+  // Ensure that foo become a data field.
+  CompileRun("p.foo = function() {}");
   Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
   fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
   Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
   templ2->Set(isolate, "a", v8_num(12));
   templ2->Set(isolate, "b", templ1);
+  templ2->Set(v8_str("bar"), acc);
+  templ2->SetAccessorProperty(v8_str("acc"), acc);
   Local<v8::Object> instance2 =
       templ2->NewInstance(env.local()).ToLocalChecked();
   CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
-  CHECK(v8_compile("(q.nirk == 123)")
-            ->Run(env.local())
-            .ToLocalChecked()
+  CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q.a == 12)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q.b !== p)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q.acc == 42)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q.bar == acc)")->BooleanValue(env.local()).FromJust());
+
+  instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
+  CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
+  CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q2.a == 12)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(env.local()).FromJust());
+
+  CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(env.local()).FromJust());
+  CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")
             ->BooleanValue(env.local())
             .FromJust());
-  CHECK(v8_compile("(q.a == 12)")
-            ->Run(env.local())
-            .ToLocalChecked()
+  CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
+                   "(desc1.get === acc)")
             ->BooleanValue(env.local())
             .FromJust());
-  CHECK(v8_compile("(q.b.x == 10)")
-            ->Run(env.local())
-            .ToLocalChecked()
-            ->BooleanValue(env.local())
-            .FromJust());
-  CHECK(v8_compile("(q.b.y == 13)")
-            ->Run(env.local())
-            .ToLocalChecked()
+  CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
+                   "(desc2.get === acc)")
             ->BooleanValue(env.local())
             .FromJust());
 }
 
+THREADED_TEST(IntegerValue) {
+  LocalContext env;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+
+  CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
+}
+
+static void GetNirk(Local<String> name,
+                    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  info.GetReturnValue().Set(v8_num(900));
+}
+
+static void GetRino(Local<String> name,
+                    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  info.GetReturnValue().Set(v8_num(560));
+}
+
+enum ObjectInstantiationMode {
+  // Create object using ObjectTemplate::NewInstance.
+  ObjectTemplate_NewInstance,
+  // Create object using FunctionTemplate::NewInstance on constructor.
+  Constructor_GetFunction_NewInstance,
+  // Create object using new operator on constructor.
+  Constructor_GetFunction_New
+};
+
+// Test object instance creation using a function template with an instance
+// template inherited from another function template with accessors and data
+// properties in prototype template.
+static void TestObjectTemplateInheritedWithPrototype(
+    ObjectInstantiationMode mode) {
+  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"));
+  v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
+  prototype_templ->Set(isolate, "a", v8_num(113));
+  prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
+  prototype_templ->Set(isolate, "b", v8_num(153));
+
+  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);
+  prototype_templ = fun_B->PrototypeTemplate();
+  prototype_templ->Set(isolate, "c", v8_num(713));
+  prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
+  prototype_templ->Set(isolate, "d", v8_num(753));
+
+  Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
+  templ->Set(isolate, "x", v8_num(10));
+  templ->Set(isolate, "y", v8_num(13));
+
+  // Perform several iterations to trigger creation from cached boilerplate.
+  for (int i = 0; i < 3; i++) {
+    Local<v8::Object> instance;
+    switch (mode) {
+      case ObjectTemplate_NewInstance:
+        instance = templ->NewInstance(env.local()).ToLocalChecked();
+        break;
+
+      case Constructor_GetFunction_NewInstance: {
+        Local<v8::Function> function_B =
+            fun_B->GetFunction(env.local()).ToLocalChecked();
+        instance = function_B->NewInstance(env.local()).ToLocalChecked();
+        break;
+      }
+      case Constructor_GetFunction_New: {
+        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());
+        }
+        instance =
+            CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+
+    CHECK(class_name->StrictEquals(instance->GetConstructorName()));
+    CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
+
+    CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
+    CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
+
+    CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
+    CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
+    CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
+    CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
+    CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
+    CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
+  }
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
+  TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
+  TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
+  TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
+}
+
+// Test object instance creation using a function template without an instance
+// template inherited from another function template.
+static void TestObjectTemplateInheritedWithoutInstanceTemplate(
+    ObjectInstantiationMode mode) {
+  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);
+
+  // Perform several iterations to trigger creation from cached boilerplate.
+  for (int i = 0; i < 3; i++) {
+    Local<v8::Object> instance;
+    switch (mode) {
+      case Constructor_GetFunction_NewInstance: {
+        Local<v8::Function> function_B =
+            fun_B->GetFunction(env.local()).ToLocalChecked();
+        instance = function_B->NewInstance(env.local()).ToLocalChecked();
+        break;
+      }
+      case Constructor_GetFunction_New: {
+        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());
+        }
+        instance =
+            CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+
+    CHECK(class_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());
+  }
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
+  TestObjectTemplateInheritedWithoutInstanceTemplate(
+      Constructor_GetFunction_NewInstance);
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
+  TestObjectTemplateInheritedWithoutInstanceTemplate(
+      Constructor_GetFunction_New);
+}
 
 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
@@ -2020,31 +2219,12 @@
                                                   ->NewInstance(env.local())
                                                   .ToLocalChecked())
             .FromJust());
-  CHECK_EQ(17.2, v8_compile("obj.flabby()")
-                     ->Run(env.local())
-                     .ToLocalChecked()
-                     ->NumberValue(env.local())
-                     .FromJust());
-  CHECK(v8_compile("'flabby' in obj")
-            ->Run(env.local())
-            .ToLocalChecked()
-            ->BooleanValue(env.local())
-            .FromJust());
-  CHECK_EQ(15.2, v8_compile("obj.knurd")
-                     ->Run(env.local())
-                     .ToLocalChecked()
-                     ->NumberValue(env.local())
-                     .FromJust());
-  CHECK(v8_compile("'knurd' in obj")
-            ->Run(env.local())
-            .ToLocalChecked()
-            ->BooleanValue(env.local())
-            .FromJust());
-  CHECK_EQ(20.1, v8_compile("obj.v1")
-                     ->Run(env.local())
-                     .ToLocalChecked()
-                     ->NumberValue(env.local())
-                     .FromJust());
+  CHECK_EQ(17.2,
+           CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
+  CHECK(CompileRun("'flabby' in obj")->BooleanValue(env.local()).FromJust());
+  CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
+  CHECK(CompileRun("'knurd' in obj")->BooleanValue(env.local()).FromJust());
+  CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
 
   CHECK(env->Global()
             ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
@@ -2052,36 +2232,106 @@
                                                    ->NewInstance(env.local())
                                                    .ToLocalChecked())
             .FromJust());
-  CHECK_EQ(17.2, v8_compile("obj2.flabby()")
-                     ->Run(env.local())
-                     .ToLocalChecked()
-                     ->NumberValue(env.local())
-                     .FromJust());
-  CHECK(v8_compile("'flabby' in obj2")
-            ->Run(env.local())
-            .ToLocalChecked()
-            ->BooleanValue(env.local())
-            .FromJust());
-  CHECK_EQ(15.2, v8_compile("obj2.knurd")
-                     ->Run(env.local())
-                     .ToLocalChecked()
-                     ->NumberValue(env.local())
-                     .FromJust());
-  CHECK(v8_compile("'knurd' in obj2")
-            ->Run(env.local())
-            .ToLocalChecked()
-            ->BooleanValue(env.local())
-            .FromJust());
-  CHECK_EQ(10.1, v8_compile("obj2.v2")
-                     ->Run(env.local())
-                     .ToLocalChecked()
-                     ->NumberValue(env.local())
-                     .FromJust());
+  CHECK_EQ(17.2,
+           CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
+  CHECK(CompileRun("'flabby' in obj2")->BooleanValue(env.local()).FromJust());
+  CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
+  CHECK(CompileRun("'knurd' in obj2")->BooleanValue(env.local()).FromJust());
+  CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
 
   // base1 and base2 cannot cross reference to each's prototype
-  CHECK(v8_compile("obj.v2")->Run(env.local()).ToLocalChecked()->IsUndefined());
-  CHECK(
-      v8_compile("obj2.v1")->Run(env.local()).ToLocalChecked()->IsUndefined());
+  CHECK(CompileRun("obj.v2")->IsUndefined());
+  CHECK(CompileRun("obj2.v1")->IsUndefined());
+}
+
+THREADED_TEST(DescriptorInheritance2) {
+  LocalContext env;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
+  fun_A->SetClassName(v8_str("A"));
+  fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
+  fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
+  fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
+
+  v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
+  fun_B->SetClassName(v8_str("B"));
+  fun_B->Inherit(fun_A);
+
+  v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
+  fun_C->SetClassName(v8_str("C"));
+  fun_C->Inherit(fun_B);
+  fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
+  fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
+  fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
+
+  v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
+  fun_D->SetClassName(v8_str("D"));
+  fun_D->Inherit(fun_C);
+
+  v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
+  fun_E->SetClassName(v8_str("E"));
+  fun_E->Inherit(fun_D);
+  fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
+  fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
+  fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
+
+  v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
+  fun_F->SetClassName(v8_str("F"));
+  fun_F->Inherit(fun_E);
+  v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
+  const int kDataPropertiesNumber = 100;
+  for (int i = 0; i < kDataPropertiesNumber; i++) {
+    v8::Local<v8::Value> val = v8_num(i);
+    v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
+    v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
+
+    templ->Set(name, val);
+    templ->Set(val_str, val);
+  }
+
+  CHECK(env->Global()
+            ->Set(env.local(), v8_str("F"),
+                  fun_F->GetFunction(env.local()).ToLocalChecked())
+            .FromJust());
+
+  v8::Local<v8::Script> script = v8_compile("o = new F()");
+
+  for (int i = 0; i < 100; i++) {
+    v8::HandleScope scope(isolate);
+    script->Run(env.local()).ToLocalChecked();
+  }
+  v8::Local<v8::Object> object = script->Run(env.local())
+                                     .ToLocalChecked()
+                                     ->ToObject(env.local())
+                                     .ToLocalChecked();
+
+  CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
+  CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
+  CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
+
+  CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
+  CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
+  CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
+
+  CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
+  CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
+  CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
+
+  for (int i = 0; i < kDataPropertiesNumber; i++) {
+    v8::Local<v8::Value> val = v8_num(i);
+    v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
+    v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
+
+    CHECK_EQ(i, object->Get(env.local(), name)
+                    .ToLocalChecked()
+                    ->IntegerValue(env.local())
+                    .FromJust());
+    CHECK_EQ(i, object->Get(env.local(), val)
+                    .ToLocalChecked()
+                    ->IntegerValue(env.local())
+                    .FromJust());
+  }
 }
 
 
@@ -2135,7 +2385,7 @@
 }
 
 
-THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
+THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
   LocalContext env;
@@ -2145,11 +2395,11 @@
   CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
   CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
-  // But we should still have an ExecutableAccessorInfo.
+  // But we should still have an AccessorInfo.
   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
   i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
-  CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
+  CHECK(it.GetAccessors()->IsAccessorInfo());
 }
 
 
@@ -7779,7 +8029,6 @@
   ApiTestFuzzer::Fuzz();
   v8::Isolate* isolate = args.GetIsolate();
   Local<Context> context = isolate->GetCurrentContext();
-  CHECK(args_fun->Equals(context, args.Callee()).FromJust());
   CHECK_EQ(3, args.Length());
   CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
   CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
@@ -8940,8 +9189,11 @@
 // For use within the TestSecurityHandler() test.
 static bool g_security_callback_result = false;
 static bool SecurityTestCallback(Local<v8::Context> accessing_context,
-                                 Local<v8::Object> accessed_object) {
+                                 Local<v8::Object> accessed_object,
+                                 Local<v8::Value> data) {
   printf("a\n");
+  CHECK(!data.IsEmpty() && data->IsInt32());
+  CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
   return g_security_callback_result;
 }
 
@@ -8952,7 +9204,7 @@
   v8::HandleScope scope0(isolate);
   v8::Local<v8::ObjectTemplate> global_template =
       v8::ObjectTemplate::New(isolate);
-  global_template->SetAccessCheckCallback(SecurityTestCallback);
+  global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
   // Create an environment
   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   context0->Enter();
@@ -9138,7 +9390,8 @@
 static bool security_check_with_gc_called;
 
 static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
-                                       Local<v8::Object> accessed_object) {
+                                       Local<v8::Object> accessed_object,
+                                       Local<v8::Value> data) {
   CcTest::heap()->CollectAllGarbage();
   security_check_with_gc_called = true;
   return true;
@@ -9625,7 +9878,8 @@
 
 static bool allowed_access = false;
 static bool AccessBlocker(Local<v8::Context> accessing_context,
-                          Local<v8::Object> accessed_object) {
+                          Local<v8::Object> accessed_object,
+                          Local<v8::Value> data) {
   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   return context->Global()->Equals(context, accessed_object).FromJust() ||
          allowed_access;
@@ -9919,9 +10173,9 @@
   CHECK_EQ(42, g_echo_value);  // Make sure we didn't call the setter.
 }
 
-
 static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
-                                Local<v8::Object> global) {
+                                Local<v8::Object> global,
+                                Local<v8::Value> data) {
   i::PrintF("Access blocked.\n");
   return false;
 }
@@ -10065,7 +10319,8 @@
 static int access_count = 0;
 
 static bool AccessCounter(Local<v8::Context> accessing_context,
-                          Local<v8::Object> accessed_object) {
+                          Local<v8::Object> accessed_object,
+                          Local<v8::Value> data) {
   access_count++;
   return true;
 }
@@ -10724,7 +10979,8 @@
   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   t2->SetHiddenPrototype(true);
   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
-  t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
+  t2->InstanceTemplate()->Set(v8_str("objects"),
+                              v8::ObjectTemplate::New(isolate));
   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   t3->SetHiddenPrototype(true);
@@ -10772,6 +11028,7 @@
   ExpectTrue("names.indexOf(\"boo\") >= 0");
   ExpectTrue("names.indexOf(\"foo\") >= 0");
   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
+  ExpectTrue("names.indexOf(\"objects\") >= 0");
   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
   ExpectFalse("names[1005] == undefined");
 }
@@ -12793,6 +13050,203 @@
 }
 
 
+static void ShouldThrowOnErrorGetter(
+    Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  v8::Isolate* isolate = info.GetIsolate();
+  Local<Boolean> should_throw_on_error =
+      Boolean::New(isolate, info.ShouldThrowOnError());
+  info.GetReturnValue().Set(should_throw_on_error);
+}
+
+
+template <typename T>
+static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
+                                     const v8::PropertyCallbackInfo<T>& info) {
+  ApiTestFuzzer::Fuzz();
+  v8::Isolate* isolate = info.GetIsolate();
+  auto context = isolate->GetCurrentContext();
+  Local<Boolean> should_throw_on_error_value =
+      Boolean::New(isolate, info.ShouldThrowOnError());
+  CHECK(context->Global()
+            ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
+                  should_throw_on_error_value)
+            .FromJust());
+}
+
+
+THREADED_TEST(AccessorShouldThrowOnError) {
+  i::FLAG_strong_mode = true;
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<Object> global = context->Global();
+
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
+  Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
+  instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
+                              ShouldThrowOnErrorSetter<void>);
+
+  Local<v8::Object> instance = templ->GetFunction(context.local())
+                                   .ToLocalChecked()
+                                   ->NewInstance(context.local())
+                                   .ToLocalChecked();
+
+  CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
+
+  // SLOPPY mode
+  Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
+  CHECK(value->IsFalse());
+  v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_setter"))
+              .ToLocalChecked();
+  CHECK(value->IsFalse());
+
+  // STRICT mode
+  value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
+  CHECK(value->IsFalse());
+  v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_setter"))
+              .ToLocalChecked();
+  CHECK(value->IsTrue());
+
+  // STRONG mode
+  value = v8_compile("'use strong';o.f")->Run(context.local()).ToLocalChecked();
+  CHECK(value->IsFalse());
+  v8_compile("'use strong'; o.f = 153")->Run(context.local()).ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_setter"))
+              .ToLocalChecked();
+  CHECK(value->IsTrue());
+}
+
+
+static void ShouldThrowOnErrorQuery(
+    Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
+  ApiTestFuzzer::Fuzz();
+  v8::Isolate* isolate = info.GetIsolate();
+  info.GetReturnValue().Set(v8::None);
+
+  auto context = isolate->GetCurrentContext();
+  Local<Boolean> should_throw_on_error_value =
+      Boolean::New(isolate, info.ShouldThrowOnError());
+  CHECK(context->Global()
+            ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
+                  should_throw_on_error_value)
+            .FromJust());
+}
+
+
+static void ShouldThrowOnErrorDeleter(
+    Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+  ApiTestFuzzer::Fuzz();
+  v8::Isolate* isolate = info.GetIsolate();
+  info.GetReturnValue().Set(v8::True(isolate));
+
+  auto context = isolate->GetCurrentContext();
+  Local<Boolean> should_throw_on_error_value =
+      Boolean::New(isolate, info.ShouldThrowOnError());
+  CHECK(context->Global()
+            ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
+                  should_throw_on_error_value)
+            .FromJust());
+}
+
+
+static void ShouldThrowOnErrorPropertyEnumerator(
+    const v8::PropertyCallbackInfo<v8::Array>& info) {
+  ApiTestFuzzer::Fuzz();
+  v8::Isolate* isolate = info.GetIsolate();
+  Local<v8::Array> names = v8::Array::New(isolate, 1);
+  CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
+  info.GetReturnValue().Set(names);
+
+  auto context = isolate->GetCurrentContext();
+  Local<Boolean> should_throw_on_error_value =
+      Boolean::New(isolate, info.ShouldThrowOnError());
+  CHECK(context->Global()
+            ->Set(isolate->GetCurrentContext(),
+                  v8_str("should_throw_enumerator"),
+                  should_throw_on_error_value)
+            .FromJust());
+}
+
+
+THREADED_TEST(InterceptorShouldThrowOnError) {
+  i::FLAG_strong_mode = true;
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<Object> global = context->Global();
+
+  auto interceptor_templ = v8::ObjectTemplate::New(isolate);
+  v8::NamedPropertyHandlerConfiguration handler(
+      ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
+      ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
+      ShouldThrowOnErrorPropertyEnumerator);
+  interceptor_templ->SetHandler(handler);
+
+  Local<v8::Object> instance =
+      interceptor_templ->NewInstance(context.local()).ToLocalChecked();
+
+  CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
+
+  // SLOPPY mode
+  Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
+  CHECK(value->IsFalse());
+  v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_setter"))
+              .ToLocalChecked();
+  CHECK(value->IsFalse());
+
+  v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_deleter"))
+              .ToLocalChecked();
+  CHECK(value->IsFalse());
+
+  v8_compile("Object.getOwnPropertyNames(o)")
+      ->Run(context.local())
+      .ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_enumerator"))
+              .ToLocalChecked();
+  CHECK(value->IsFalse());
+
+  // STRICT mode
+  value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
+  CHECK(value->IsFalse());
+  v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_setter"))
+              .ToLocalChecked();
+  CHECK(value->IsTrue());
+
+  v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_deleter"))
+              .ToLocalChecked();
+  CHECK(value->IsTrue());
+
+  v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
+      ->Run(context.local())
+      .ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_enumerator"))
+              .ToLocalChecked();
+  CHECK(value->IsFalse());
+
+  // STRONG mode
+  value = v8_compile("'use strong';o.f")->Run(context.local()).ToLocalChecked();
+  CHECK(value->IsFalse());
+  v8_compile("'use strong'; o.f = 153")->Run(context.local()).ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_setter"))
+              .ToLocalChecked();
+  CHECK(value->IsTrue());
+
+  v8_compile("'use strong'; Object.getOwnPropertyNames(o)")
+      ->Run(context.local())
+      .ToLocalChecked();
+  value = global->Get(context.local(), v8_str("should_throw_enumerator"))
+              .ToLocalChecked();
+  CHECK(value->IsFalse());
+}
+
+
 static void IsConstructHandler(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
@@ -19780,7 +20234,7 @@
   Context::Scope scope(other_context);
   CHECK(bound_function1->CreationContext() == context1);
   CheckContextId(bound_function1, 1);
-  CHECK(bound_function2->CreationContext() == context2);
+  CHECK(bound_function2->CreationContext() == context1);
   CheckContextId(bound_function2, 1);
 }
 
@@ -20171,16 +20625,20 @@
 
   context->Exit();
 
-  // Template for object for second context. Values to test are put on it as
-  // properties.
-  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
-  global_template->Set(v8_str("simple"), simple_object);
-  global_template->Set(v8_str("protected"), protected_object);
-  global_template->Set(v8_str("global"), global_object);
-  global_template->Set(v8_str("proxy"), proxy_object);
-  global_template->Set(v8_str("hidden"), object_with_hidden);
+  LocalContext context2;
+  v8::Local<v8::Object> global = context2->Global();
 
-  LocalContext context2(NULL, global_template);
+  // Setup global variables.
+  CHECK(global->Set(context2.local(), v8_str("simple"), simple_object)
+            .FromJust());
+  CHECK(global->Set(context2.local(), v8_str("protected"), protected_object)
+            .FromJust());
+  CHECK(global->Set(context2.local(), v8_str("global"), global_object)
+            .FromJust());
+  CHECK(
+      global->Set(context2.local(), v8_str("proxy"), proxy_object).FromJust());
+  CHECK(global->Set(context2.local(), v8_str("hidden"), object_with_hidden)
+            .FromJust());
 
   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
   CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
@@ -20332,20 +20790,34 @@
 
 
 uint8_t callback_fired = 0;
+uint8_t before_call_entered_callback_count1 = 0;
+uint8_t before_call_entered_callback_count2 = 0;
 
 
-void CallCompletedCallback1() {
+void CallCompletedCallback1(v8::Isolate*) {
   v8::base::OS::Print("Firing callback 1.\n");
   callback_fired ^= 1;  // Toggle first bit.
 }
 
 
-void CallCompletedCallback2() {
+void CallCompletedCallback2(v8::Isolate*) {
   v8::base::OS::Print("Firing callback 2.\n");
   callback_fired ^= 2;  // Toggle second bit.
 }
 
 
+void BeforeCallEnteredCallback1(v8::Isolate*) {
+  v8::base::OS::Print("Firing before call entered callback 1.\n");
+  before_call_entered_callback_count1++;
+}
+
+
+void BeforeCallEnteredCallback2(v8::Isolate*) {
+  v8::base::OS::Print("Firing before call entered callback 2.\n");
+  before_call_entered_callback_count2++;
+}
+
+
 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   int32_t level =
       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
@@ -20378,36 +20850,54 @@
   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
+  env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
+  env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
+  env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   v8::base::OS::Print("--- Script (1) ---\n");
+  callback_fired = 0;
+  before_call_entered_callback_count1 = 0;
+  before_call_entered_callback_count2 = 0;
   Local<Script> script =
       v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
   script->Run(env.local()).ToLocalChecked();
   CHECK_EQ(3, callback_fired);
+  CHECK_EQ(4, before_call_entered_callback_count1);
+  CHECK_EQ(4, before_call_entered_callback_count2);
 
   v8::base::OS::Print("\n--- Script (2) ---\n");
   callback_fired = 0;
+  before_call_entered_callback_count1 = 0;
+  before_call_entered_callback_count2 = 0;
   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
+  env->GetIsolate()->RemoveBeforeCallEnteredCallback(
+      BeforeCallEnteredCallback1);
   script->Run(env.local()).ToLocalChecked();
   CHECK_EQ(2, callback_fired);
+  CHECK_EQ(0, before_call_entered_callback_count1);
+  CHECK_EQ(4, before_call_entered_callback_count2);
 
   v8::base::OS::Print("\n--- Function ---\n");
   callback_fired = 0;
+  before_call_entered_callback_count1 = 0;
+  before_call_entered_callback_count2 = 0;
   Local<Function> recursive_function = Local<Function>::Cast(
       env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
   v8::Local<Value> args[] = {v8_num(0)};
   recursive_function->Call(env.local(), env->Global(), 1, args)
       .ToLocalChecked();
   CHECK_EQ(2, callback_fired);
+  CHECK_EQ(0, before_call_entered_callback_count1);
+  CHECK_EQ(4, before_call_entered_callback_count2);
 }
 
 
-void CallCompletedCallbackNoException() {
+void CallCompletedCallbackNoException(v8::Isolate*) {
   v8::HandleScope scope(CcTest::isolate());
   CompileRun("1+1;");
 }
 
 
-void CallCompletedCallbackException() {
+void CallCompletedCallbackException(v8::Isolate*) {
   v8::HandleScope scope(CcTest::isolate());
   CompileRun("throw 'second exception';");
 }
@@ -21676,9 +22166,8 @@
     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
     v8::Local<v8::Template> proto = t->PrototypeTemplate();
     proto->Set(v8_str("shouldContinue"),
-               Function::New(env_.local(), ShouldContinueCallback,
-                             v8::External::New(isolate_, this))
-                   .ToLocalChecked());
+               FunctionTemplate::New(isolate_, ShouldContinueCallback,
+                                     v8::External::New(isolate_, this)));
     CHECK(env_->Global()
               ->Set(env_.local(), v8_str("Klass"),
                     t->GetFunction(env_.local()).ToLocalChecked())
@@ -21744,9 +22233,8 @@
     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
     v8::Local<v8::Template> proto = t->PrototypeTemplate();
     proto->Set(v8_str("shouldContinue"),
-               Function::New(env_.local(), ShouldContinueCallback,
-                             v8::External::New(isolate_, this))
-                   .ToLocalChecked());
+               FunctionTemplate::New(isolate_, ShouldContinueCallback,
+                                     v8::External::New(isolate_, this)));
     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
     instance_template->SetHandler(
         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
@@ -21958,7 +22446,7 @@
                        ->get_api_func_data()
                        ->serial_number()),
       i_isolate);
-  auto cache = i_isolate->function_cache();
+  auto cache = i_isolate->template_instantiations_cache();
   CHECK(cache->Lookup(serial_number)->IsTheHole());
   // Verify that each Function::New creates a new function instance
   Local<Object> data2 = v8::Object::New(isolate);
@@ -22034,7 +22522,6 @@
 
   static void OptimizationCallback(
       const v8::FunctionCallbackInfo<v8::Value>& info) {
-    CHECK(callee == info.Callee());
     CHECK(data == info.Data());
     CHECK(receiver == info.This());
     if (info.Length() == 1) {
@@ -23699,16 +24186,16 @@
 
 static bool access_was_called = false;
 
-
 static bool AccessAlwaysAllowedWithFlag(Local<v8::Context> accessing_context,
-                                        Local<v8::Object> accessed_object) {
+                                        Local<v8::Object> accessed_object,
+                                        Local<v8::Value> data) {
   access_was_called = true;
   return true;
 }
 
-
 static bool AccessAlwaysBlockedWithFlag(Local<v8::Context> accessing_context,
-                                        Local<v8::Object> accessed_object) {
+                                        Local<v8::Object> accessed_object,
+                                        Local<v8::Value> data) {
   access_was_called = true;
   return false;
 }
@@ -23970,6 +24457,37 @@
   args.GetReturnValue().Set(v8_num(7));
 }
 
+TEST(ExtrasFunctionSource) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
+
+  v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
+
+  // Functions defined in extras do not expose source code.
+  auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
+                  .ToLocalChecked()
+                  .As<v8::Function>();
+  auto undefined = v8::Undefined(isolate);
+  auto result = func->Call(env.local(), undefined, 0, {})
+                    .ToLocalChecked()
+                    .As<v8::String>();
+  CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
+
+  // Functions defined in extras do not show up in the stack trace.
+  auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
+                     .ToLocalChecked()
+                     .As<v8::Function>();
+  CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
+  ExpectString(
+      "function f(x) { return wrapper(x) }"
+      "function g() { return new Error().stack; }"
+      "f(g)",
+      "Error\n"
+      "    at g (<anonymous>:1:58)\n"
+      "    at f (<anonymous>:1:24)\n"
+      "    at <anonymous>:1:78");
+}
 
 TEST(ExtrasBindingObject) {
   v8::Isolate* isolate = CcTest::isolate();
@@ -24318,7 +24836,6 @@
 
 
 TEST(AccessCheckedIsConcatSpreadable) {
-  i::FLAG_harmony_concat_spreadable = true;
   v8::Isolate* isolate = CcTest::isolate();
   HandleScope scope(isolate);
   LocalContext env;
diff --git a/test/cctest/test-asm-validator.cc b/test/cctest/test-asm-validator.cc
index fae7500..207b915 100644
--- a/test/cctest/test-asm-validator.cc
+++ b/test/cctest/test-asm-validator.cc
@@ -16,14 +16,15 @@
 #include "test/cctest/expression-type-collector-macros.h"
 
 // Macros for function types.
-#define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(zone), zone))
+#define FUNC_FOREIGN_TYPE Bounds(Type::Function(Type::Any(), zone))
+#define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(), zone))
 #define FUNC_I_TYPE Bounds(Type::Function(cache.kAsmSigned, zone))
 #define FUNC_F_TYPE Bounds(Type::Function(cache.kAsmFloat, zone))
 #define FUNC_D_TYPE Bounds(Type::Function(cache.kAsmDouble, zone))
 #define FUNC_D2D_TYPE \
   Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, zone))
 #define FUNC_N2F_TYPE \
-  Bounds(Type::Function(cache.kAsmFloat, Type::Number(zone), zone))
+  Bounds(Type::Function(cache.kAsmFloat, Type::Number(), zone))
 #define FUNC_I2I_TYPE \
   Bounds(Type::Function(cache.kAsmSigned, cache.kAsmInt, zone))
 #define FUNC_II2D_TYPE \
@@ -33,11 +34,10 @@
 #define FUNC_DD2D_TYPE                                                        \
   Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, cache.kAsmDouble, \
                         zone))
-#define FUNC_NN2N_TYPE                                          \
-  Bounds(Type::Function(Type::Number(zone), Type::Number(zone), \
-                        Type::Number(zone), zone))
+#define FUNC_NN2N_TYPE \
+  Bounds(Type::Function(Type::Number(), Type::Number(), Type::Number(), zone))
 #define FUNC_N2N_TYPE \
-  Bounds(Type::Function(Type::Number(zone), Type::Number(zone), zone))
+  Bounds(Type::Function(Type::Number(), Type::Number(), zone))
 
 // Macros for array types.
 #define FLOAT64_ARRAY_TYPE Bounds(Type::Array(cache.kAsmDouble, zone))
@@ -265,7 +265,7 @@
         }
       }
       // "use asm";
-      CHECK_EXPR(Literal, Bounds(Type::String(zone)));
+      CHECK_EXPR(Literal, Bounds(Type::String()));
       // var exp = stdlib.Math.exp;
       CHECK_EXPR(Assignment, FUNC_D2D_TYPE) {
         CHECK_VAR(exp, FUNC_D2D_TYPE);
@@ -518,12 +518,11 @@
     CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
 #define CHECK_FUNC_TYPES_END_1()                           \
   /* "use asm"; */                                         \
-  CHECK_EXPR(Literal, Bounds(Type::String(zone)));         \
+  CHECK_EXPR(Literal, Bounds(Type::String()));             \
   /* stdlib shortcuts. */                                  \
   CheckStdlibShortcuts1(zone, types, index, depth, cache); \
   CheckStdlibShortcuts2(zone, types, index, depth, cache);
 
-
 #define CHECK_FUNC_TYPES_END_2()                   \
   /* return { foo: foo }; */                       \
   CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) { \
@@ -564,10 +563,10 @@
       "function foo() { bar(); }") {
     CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
       // return undefined;
-      CHECK_EXPR(Literal, Bounds(Type::Undefined(zone)));
+      CHECK_EXPR(Literal, Bounds(Type::Undefined()));
     }
     CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
-      CHECK_EXPR(Call, Bounds(Type::Undefined(zone))) {
+      CHECK_EXPR(Call, Bounds(Type::Undefined())) {
         CHECK_VAR(bar, FUNC_V_TYPE);
       }
     }
@@ -582,7 +581,7 @@
       "function foo() { bar(); }") {
     CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE);
     CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
-      CHECK_EXPR(Call, Bounds(Type::Undefined(zone))) {
+      CHECK_EXPR(Call, Bounds(Type::Undefined())) {
         CHECK_VAR(bar, FUNC_V_TYPE);
       }
     }
@@ -602,7 +601,7 @@
       }
     }
     CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
-      CHECK_EXPR(Call, Bounds(Type::Undefined(zone))) {
+      CHECK_EXPR(Call, Bounds(Type::Undefined())) {
         CHECK_VAR(bar, FUNC_V_TYPE);
       }
     }
@@ -1066,7 +1065,7 @@
         CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
       }
       CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
-        CHECK_EXPR(BinaryOperation, Bounds(Type::None(zone), Type::Any(zone))) {
+        CHECK_EXPR(BinaryOperation, Bounds(Type::None(), Type::Any())) {
           CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) {
             CHECK_VAR(x, Bounds(cache.kAsmInt));
             CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
@@ -1327,7 +1326,7 @@
           CHECK_EXPR(Property, Bounds(cache.kAsmInt)) {
             CHECK_VAR(i8, Bounds(cache.kInt8Array));
             CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
-              CHECK_VAR(x, Bounds(cache.kAsmSigned));
+              CHECK_VAR(x, Bounds(cache.kAsmInt));
               CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
             }
           }
@@ -1387,7 +1386,7 @@
         CHECK_EXPR(Property, Bounds::Unbounded()) {
           CHECK_VAR(i8, Bounds(cache.kInt8Array));
           CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
-            CHECK_VAR(x, Bounds(cache.kAsmSigned));
+            CHECK_VAR(x, Bounds(cache.kAsmInt));
             CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
           }
         }
@@ -1435,6 +1434,71 @@
   CHECK_FUNC_TYPES_END
 }
 
+TEST(StoreIntish) {
+  CHECK_FUNC_TYPES_BEGIN(
+      "function bar() { var x = 1; var y = 1; i32[0] = x + y; }\n"
+      "function foo() { bar(); }") {
+    CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+        CHECK_VAR(x, Bounds(cache.kAsmInt));
+        CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+      }
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+        CHECK_VAR(y, Bounds(cache.kAsmInt));
+        CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+      }
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+        CHECK_EXPR(Property, Bounds::Unbounded()) {
+          CHECK_VAR(i32, Bounds(cache.kInt32Array));
+          CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+        }
+        CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
+          CHECK_VAR(x, Bounds(cache.kAsmInt));
+          CHECK_VAR(y, Bounds(cache.kAsmInt));
+        }
+      }
+    }
+    CHECK_SKIP();
+  }
+  CHECK_FUNC_TYPES_END
+}
+
+TEST(StoreFloatish) {
+  CHECK_FUNC_TYPES_BEGIN(
+      "function bar() { "
+      "var x = fround(1.0); "
+      "var y = fround(1.0); f32[0] = x + y; }\n"
+      "function foo() { bar(); }") {
+    CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
+        CHECK_VAR(x, Bounds(cache.kAsmFloat));
+        CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
+          CHECK_VAR(fround, FUNC_N2F_TYPE);
+          CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
+        }
+      }
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
+        CHECK_VAR(y, Bounds(cache.kAsmFloat));
+        CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
+          CHECK_VAR(fround, FUNC_N2F_TYPE);
+          CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
+        }
+      }
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
+        CHECK_EXPR(Property, Bounds::Unbounded()) {
+          CHECK_VAR(f32, Bounds(cache.kFloat32Array));
+          CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+        }
+        CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmFloat)) {
+          CHECK_VAR(x, Bounds(cache.kAsmFloat));
+          CHECK_VAR(y, Bounds(cache.kAsmFloat));
+        }
+      }
+    }
+    CHECK_SKIP();
+  }
+  CHECK_FUNC_TYPES_END
+}
 
 TEST(Load1Constant) {
   CHECK_FUNC_TYPES_BEGIN(
@@ -1522,7 +1586,9 @@
           CHECK_EXPR(Property, FUNC_I2I_TYPE) {
             CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE);
             CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
-              CHECK_VAR(x, Bounds(cache.kAsmSigned));
+              // TODO(bradnelson): revert this
+              // CHECK_VAR(x, Bounds(cache.kAsmSigned));
+              CHECK_VAR(x, Bounds(cache.kAsmInt));
               CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
             }
           }
@@ -1711,9 +1777,9 @@
 
 TEST(AssignToFloatishToF64) {
   CHECK_FUNC_ERROR(
-      "function bar() { var v = fround(1.0); f32[0] = v + fround(1.0); }\n"
+      "function bar() { var v = fround(1.0); f64[0] = v + fround(1.0); }\n"
       "function foo() { bar(); }",
-      "asm: line 39: intish or floatish assignment\n");
+      "asm: line 39: floatish assignment to double array\n");
 }
 
 
@@ -1724,8 +1790,8 @@
       "function foo() { bar(); }") {
     CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
       CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
-        CHECK_EXPR(Call, Bounds(Type::Number(zone))) {
-          CHECK_VAR(baz, Bounds(Type::Any(zone)));
+        CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) {
+          CHECK_VAR(baz, FUNC_FOREIGN_TYPE);
           CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
           CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
         }
@@ -1739,9 +1805,9 @@
     }
   }
   CHECK_FUNC_TYPES_END_1()
-  CHECK_EXPR(Assignment, Bounds(Type::Any(zone))) {
-    CHECK_VAR(baz, Bounds(Type::Any(zone)));
-    CHECK_EXPR(Property, Bounds(Type::Any(zone))) {
+  CHECK_EXPR(Assignment, Bounds(FUNC_FOREIGN_TYPE)) {
+    CHECK_VAR(baz, Bounds(FUNC_FOREIGN_TYPE));
+    CHECK_EXPR(Property, Bounds(FUNC_FOREIGN_TYPE)) {
       CHECK_VAR(foreign, Bounds::Unbounded());
       CHECK_EXPR(Literal, Bounds::Unbounded());
     }
@@ -1749,6 +1815,28 @@
   CHECK_FUNC_TYPES_END_2()
 }
 
+TEST(ByteArray) {
+  // Forbidden by asm.js spec, present in embenchen.
+  CHECK_FUNC_TYPES_BEGIN(
+      "function bar() { var x = 0; i8[x] = 2; }\n"
+      "function foo() { bar(); }") {
+    CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+        CHECK_VAR(x, Bounds(cache.kAsmInt));
+        CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+      }
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+        CHECK_EXPR(Property, Bounds::Unbounded()) {
+          CHECK_VAR(i8, Bounds(cache.kInt8Array));
+          CHECK_VAR(x, Bounds(cache.kAsmSigned));
+        }
+        CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+      }
+    }
+    CHECK_SKIP();
+  }
+  CHECK_FUNC_TYPES_END
+}
 
 TEST(BadExports) {
   HARNESS_PREAMBLE()
@@ -1767,7 +1855,14 @@
 
 TEST(NestedHeapAssignment) {
   CHECK_FUNC_ERROR(
-      "function bar() { var x = 0; i8[x = 1] = 2; }\n"
+      "function bar() { var x = 0; i16[x = 1] = 2; }\n"
+      "function foo() { bar(); }",
+      "asm: line 39: expected >> in heap access\n");
+}
+
+TEST(BadOperatorHeapAssignment) {
+  CHECK_FUNC_ERROR(
+      "function bar() { var x = 0; i16[x & 1] = 2; }\n"
       "function foo() { bar(); }",
       "asm: line 39: expected >> in heap access\n");
 }
@@ -1786,7 +1881,7 @@
       "var s0 = sin(0);\n"
       "function bar() { }\n"
       "function foo() { bar(); }",
-      "asm: line 39: calls forbidden outside function bodies\n");
+      "asm: line 39: illegal variable reference in module body\n");
 }
 
 
@@ -1795,7 +1890,7 @@
       "function bar() { return 0.0; }\n"
       "var s0 = bar(0);\n"
       "function foo() { bar(); }",
-      "asm: line 40: calls forbidden outside function bodies\n");
+      "asm: line 40: illegal variable reference in module body\n");
 }
 
 
@@ -1835,7 +1930,7 @@
         CHECK_EXPR(Property, Bounds::Unbounded()) {
           CHECK_VAR(i8, Bounds(cache.kInt8Array));
           CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
-            CHECK_EXPR(Assignment, Bounds(cache.kAsmSigned)) {
+            CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
               CHECK_VAR(x, Bounds(cache.kAsmInt));
               CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
             }
@@ -2007,7 +2102,7 @@
           CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
         }
       }
-      CHECK_EXPR(Literal, Bounds(Type::Undefined(zone)));
+      CHECK_EXPR(Literal, Bounds(Type::Undefined()));
       CHECK_VAR(.switch_tag, Bounds(cache.kAsmSigned));
       // case 1: return 23;
       CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
@@ -2048,3 +2143,202 @@
       "function foo() { bar(); }",
       "asm: line 39: default case out of order\n");
 }
+
+TEST(BadForeignCall) {
+  const char test_function[] =
+      "function TestModule(stdlib, foreign, buffer) {\n"
+      "  \"use asm\";\n"
+      "  var ffunc = foreign.foo;\n"
+      "  function test1() { var x = 0; ffunc(x); }\n"
+      "  return { testFunc1: test1 };\n"
+      "}\n";
+  v8::V8::Initialize();
+  HandleAndZoneScope handles;
+  Zone* zone = handles.main_zone();
+  ZoneVector<ExpressionTypeEntry> types(zone);
+  CHECK_EQ(
+      "asm: line 4: foreign call argument expected to be int, double, or "
+      "fixnum\n",
+      Validate(zone, test_function, &types));
+}
+
+TEST(BadImports) {
+  const char test_function[] =
+      "function TestModule(stdlib, foreign, buffer) {\n"
+      "  \"use asm\";\n"
+      "  var fint = (foreign.bar | 0) | 0;\n"
+      "  function test1() {}\n"
+      "  return { testFunc1: test1 };\n"
+      "}\n";
+  v8::V8::Initialize();
+  HandleAndZoneScope handles;
+  Zone* zone = handles.main_zone();
+  ZoneVector<ExpressionTypeEntry> types(zone);
+  CHECK_EQ("asm: line 3: illegal computation inside module body\n",
+           Validate(zone, test_function, &types));
+}
+
+TEST(BadVariableReference) {
+  const char test_function[] =
+      "function TestModule(stdlib, foreign, buffer) {\n"
+      "  \"use asm\";\n"
+      "  var x = 0;\n"
+      "  var y = x;\n"
+      "  function test1() {}\n"
+      "  return { testFunc1: test1 };\n"
+      "}\n";
+  v8::V8::Initialize();
+  HandleAndZoneScope handles;
+  Zone* zone = handles.main_zone();
+  ZoneVector<ExpressionTypeEntry> types(zone);
+  CHECK_EQ("asm: line 4: illegal variable reference in module body\n",
+           Validate(zone, test_function, &types));
+}
+
+TEST(BadForeignVariableReferenceValueOr) {
+  const char test_function[] =
+      "function TestModule(stdlib, foreign, buffer) {\n"
+      "  \"use asm\";\n"
+      "  var fint = foreign.bar | 1;\n"
+      "}\n";
+  v8::V8::Initialize();
+  HandleAndZoneScope handles;
+  Zone* zone = handles.main_zone();
+  ZoneVector<ExpressionTypeEntry> types(zone);
+  CHECK_EQ("asm: line 3: illegal integer annotation value\n",
+           Validate(zone, test_function, &types));
+}
+
+TEST(BadForeignVariableReferenceValueOrDot) {
+  const char test_function[] =
+      "function TestModule(stdlib, foreign, buffer) {\n"
+      "  \"use asm\";\n"
+      "  var fint = foreign.bar | 1.0;\n"
+      "}\n";
+  v8::V8::Initialize();
+  HandleAndZoneScope handles;
+  Zone* zone = handles.main_zone();
+  ZoneVector<ExpressionTypeEntry> types(zone);
+  CHECK_EQ("asm: line 3: illegal integer annotation value\n",
+           Validate(zone, test_function, &types));
+}
+
+TEST(BadForeignVariableReferenceValueMul) {
+  const char test_function[] =
+      "function TestModule(stdlib, foreign, buffer) {\n"
+      "  \"use asm\";\n"
+      "  var fint = foreign.bar * 2.0;\n"
+      "}\n";
+  v8::V8::Initialize();
+  HandleAndZoneScope handles;
+  Zone* zone = handles.main_zone();
+  ZoneVector<ExpressionTypeEntry> types(zone);
+  CHECK_EQ("asm: line 3: illegal double annotation value\n",
+           Validate(zone, test_function, &types));
+}
+
+TEST(BadForeignVariableReferenceValueMulNoDot) {
+  const char test_function[] =
+      "function TestModule(stdlib, foreign, buffer) {\n"
+      "  \"use asm\";\n"
+      "  var fint = foreign.bar * 1;\n"
+      "}\n";
+  v8::V8::Initialize();
+  HandleAndZoneScope handles;
+  Zone* zone = handles.main_zone();
+  ZoneVector<ExpressionTypeEntry> types(zone);
+  CHECK_EQ("asm: line 3: ill-typed arithmetic operation\n",
+           Validate(zone, test_function, &types));
+}
+
+TEST(Imports) {
+  const char test_function[] =
+      "function TestModule(stdlib, foreign, buffer) {\n"
+      "  \"use asm\";\n"
+      "  var ffunc = foreign.foo;\n"
+      "  var fint = foreign.bar | 0;\n"
+      "  var fdouble = +foreign.baz;\n"
+      "  function test1() { return ffunc(fint|0, fdouble) | 0; }\n"
+      "  function test2() { return +ffunc(fdouble, fint|0); }\n"
+      "  return { testFunc1: test1, testFunc2: test2 };\n"
+      "}\n";
+
+  v8::V8::Initialize();
+  HandleAndZoneScope handles;
+  Zone* zone = handles.main_zone();
+  ZoneVector<ExpressionTypeEntry> types(zone);
+  CHECK_EQ("", Validate(zone, test_function, &types));
+  TypeCache cache;
+
+  CHECK_TYPES_BEGIN {
+    // Module.
+    CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
+      // function test1
+      CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
+        CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
+          CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) {
+            CHECK_VAR(ffunc, FUNC_FOREIGN_TYPE);
+            CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
+              CHECK_VAR(fint, Bounds(cache.kAsmInt));
+              CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+            }
+            CHECK_VAR(fdouble, Bounds(cache.kAsmDouble));
+          }
+          CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+        }
+      }
+      // function test2
+      CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) {
+        CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
+          CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) {
+            CHECK_VAR(ffunc, FUNC_FOREIGN_TYPE);
+            CHECK_VAR(fdouble, Bounds(cache.kAsmDouble));
+            CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
+              CHECK_VAR(fint, Bounds(cache.kAsmInt));
+              CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+            }
+          }
+          CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
+        }
+      }
+      // "use asm";
+      CHECK_EXPR(Literal, Bounds(Type::String()));
+      // var func = foreign.foo;
+      CHECK_EXPR(Assignment, Bounds(FUNC_FOREIGN_TYPE)) {
+        CHECK_VAR(ffunc, Bounds(FUNC_FOREIGN_TYPE));
+        CHECK_EXPR(Property, Bounds(FUNC_FOREIGN_TYPE)) {
+          CHECK_VAR(foreign, Bounds::Unbounded());
+          CHECK_EXPR(Literal, Bounds::Unbounded());
+        }
+      }
+      // var fint = foreign.bar | 0;
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+        CHECK_VAR(fint, Bounds(cache.kAsmInt));
+        CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
+          CHECK_EXPR(Property, Bounds(Type::Number())) {
+            CHECK_VAR(foreign, Bounds::Unbounded());
+            CHECK_EXPR(Literal, Bounds::Unbounded());
+          }
+          CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+        }
+      }
+      // var fdouble = +foreign.baz;
+      CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
+        CHECK_VAR(fdouble, Bounds(cache.kAsmDouble));
+        CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
+          CHECK_EXPR(Property, Bounds(Type::Number())) {
+            CHECK_VAR(foreign, Bounds::Unbounded());
+            CHECK_EXPR(Literal, Bounds::Unbounded());
+          }
+          CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
+        }
+      }
+      // return { testFunc1: test1, testFunc2: test2 };
+      CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) {
+        CHECK_VAR(test1, FUNC_I_TYPE);
+        CHECK_VAR(test2, FUNC_D_TYPE);
+      }
+    }
+  }
+  CHECK_TYPES_END
+}
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index 563b050..68eaab1 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -1819,6 +1819,55 @@
 }
 
 
+#define TEST_RBIT(expected_, input_)                       \
+  t.input = input_;                                        \
+  t.result = 0;                                            \
+  dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
+  CHECK_EQ(expected_, t.result);
+
+
+TEST(rbit) {
+  CcTest::InitializeVM();
+  Isolate* const isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+  Assembler assm(isolate, nullptr, 0);
+
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    CpuFeatureScope scope(&assm, ARMv7);
+
+    typedef struct {
+      uint32_t input;
+      uint32_t result;
+    } T;
+    T t;
+
+    __ ldr(r1, MemOperand(r0, offsetof(T, input)));
+    __ rbit(r1, r1);
+    __ str(r1, MemOperand(r0, offsetof(T, result)));
+    __ bx(lr);
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Handle<Code> code = isolate->factory()->NewCode(
+        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+#ifdef OBJECT_PRINT
+    code->Print(std::cout);
+#endif
+
+    F3 f = FUNCTION_CAST<F3>(code->entry());
+    Object* dummy = NULL;
+    TEST_RBIT(0xffffffff, 0xffffffff);
+    TEST_RBIT(0x00000000, 0x00000000);
+    TEST_RBIT(0xffff0000, 0x0000ffff);
+    TEST_RBIT(0xff00ff00, 0x00ff00ff);
+    TEST_RBIT(0xf0f0f0f0, 0x0f0f0f0f);
+    TEST_RBIT(0x1e6a2c48, 0x12345678);
+    USE(dummy);
+  }
+}
+
+
 TEST(code_relative_offset) {
   // Test extracting the offset of a label from the beginning of the code
   // in a register.
diff --git a/test/cctest/test-assembler-mips.cc b/test/cctest/test-assembler-mips.cc
index 4f986ce..1928a75 100644
--- a/test/cctest/test-assembler-mips.cc
+++ b/test/cctest/test-assembler-mips.cc
@@ -384,6 +384,14 @@
 
 
 TEST(MIPS4) {
+  // Exchange between GP anf FP registers is done through memory
+  // on FPXX compiled binaries and architectures that do not support
+  // MTHC1 and MTFC1. If this is the case, skipping this test.
+  if (IsFpxxMode() &&
+      (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson))) {
+    return;
+  }
+
   // Test moves between floating point and integer registers.
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
@@ -403,7 +411,7 @@
   __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
 
   // Swap f4 and f6, by using four integer registers, t0-t3.
-  if (!IsFp64Mode()) {
+  if (IsFp32Mode()) {
     __ mfc1(t0, f4);
     __ mfc1(t1, f5);
     __ mfc1(t2, f6);
@@ -415,6 +423,7 @@
     __ mtc1(t3, f5);
   } else {
     CHECK(!IsMipsArchVariant(kMips32r1) && !IsMipsArchVariant(kLoongson));
+    DCHECK(IsFp64Mode() || IsFpxxMode());
     __ mfc1(t0, f4);
     __ mfhc1(t1, f4);
     __ mfc1(t2, f6);
@@ -425,6 +434,7 @@
     __ mtc1(t2, f4);
     __ mthc1(t3, f4);
   }
+
   // Store the swapped f4 and f5 back to memory.
   __ sdc1(f4, MemOperand(a0, offsetof(T, a)) );
   __ sdc1(f6, MemOperand(a0, offsetof(T, c)) );
@@ -811,8 +821,6 @@
 
 TEST(MIPS10) {
   // Test conversions between doubles and words.
-  // Test maps double to FP reg pairs in fp32 mode
-  // and into FP reg in fp64 mode.
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
   HandleScope scope(isolate);
@@ -830,24 +838,16 @@
   Assembler assm(isolate, NULL, 0);
   Label L, C;
 
-  if (!IsMipsArchVariant(kMips32r2)) return;
+  if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) return;
 
   // Load all structure elements to registers.
   // (f0, f1) = a (fp32), f0 = a (fp64)
   __ ldc1(f0, MemOperand(a0, offsetof(T, a)));
 
-  if (IsFp64Mode()) {
-    __ mfc1(t0, f0);  // t0 = f0(31..0)
-    __ mfhc1(t1, f0);  // t1 = sign_extend(f0(63..32))
-    __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant)));  // dbl_mant = t0
-    __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp)));  // dbl_exp = t1
-  } else {
-    // Save the raw bits of the double.
-    __ mfc1(t0, f0);  // t0 = a1
-    __ mfc1(t1, f1);  // t1 = a2
-    __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant)));  // dbl_mant = t0
-    __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp)));  // dbl_exp = t1
-  }
+  __ mfc1(t0, f0);   // t0 = f0(31..0)
+  __ mfhc1(t1, f0);  // t1 = sign_extend(f0(63..32))
+  __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant)));  // dbl_mant = t0
+  __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp)));   // dbl_exp = t1
 
   // Convert double in f0 to word, save hi/lo parts.
   __ cvt_w_d(f0, f0);  // a_word = (word)a
@@ -1456,10 +1456,10 @@
     CcTest::InitializeVM();
     Isolate* isolate = CcTest::i_isolate();
     HandleScope scope(isolate);
-    MacroAssembler assm(isolate, NULL, 0,
+    MacroAssembler assm(isolate, nullptr, 0,
                         v8::internal::CodeObjectRequired::kYes);
 
-    typedef struct test_float {
+    struct TestFloat {
       double a;
       double b;
       double c;
@@ -1468,21 +1468,35 @@
       float f;
       float g;
       float h;
-    } TestFloat;
+    };
 
     TestFloat test;
-    const double double_nan = std::numeric_limits<double>::quiet_NaN();
-    const float  float_nan = std::numeric_limits<float>::quiet_NaN();
-    const int kTableLength = 5;
-    double inputsa[kTableLength] = {2.0, 3.0, double_nan, 3.0, double_nan};
-    double inputsb[kTableLength] = {3.0, 2.0, 3.0, double_nan, double_nan};
-    double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, double_nan};
-    double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, double_nan};
+    const double dnan = std::numeric_limits<double>::quiet_NaN();
+    const double dinf = std::numeric_limits<double>::infinity();
+    const double dminf = -std::numeric_limits<double>::infinity();
+    const float fnan = std::numeric_limits<float>::quiet_NaN();
+    const float finf = std::numeric_limits<float>::infinity();
+    const float fminf = std::numeric_limits<float>::infinity();
+    const int kTableLength = 13;
+    double inputsa[kTableLength] = {2.0,  3.0,  dnan, 3.0,   -0.0, 0.0, dinf,
+                                    dnan, 42.0, dinf, dminf, dinf, dnan};
+    double inputsb[kTableLength] = {3.0,  2.0,  3.0,  dnan, 0.0,   -0.0, dnan,
+                                    dinf, dinf, 42.0, dinf, dminf, dnan};
+    double outputsdmin[kTableLength] = {2.0,   2.0,   3.0,  3.0,  -0.0,
+                                        -0.0,  dinf,  dinf, 42.0, 42.0,
+                                        dminf, dminf, dnan};
+    double outputsdmax[kTableLength] = {3.0,  3.0,  3.0,  3.0,  0.0,  0.0, dinf,
+                                        dinf, dinf, dinf, dinf, dinf, dnan};
 
-    float inputse[kTableLength] = {2.0, 3.0, float_nan, 3.0, float_nan};
-    float inputsf[kTableLength] = {3.0, 2.0, 3.0, float_nan, float_nan};
-    float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, float_nan};
-    float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, float_nan};
+    float inputse[kTableLength] = {2.0,  3.0,  fnan, 3.0,   -0.0, 0.0, finf,
+                                   fnan, 42.0, finf, fminf, finf, fnan};
+    float inputsf[kTableLength] = {3.0,  2.0,  3.0,  fnan, -0.0,  0.0, fnan,
+                                   finf, finf, 42.0, finf, fminf, fnan};
+    float outputsfmin[kTableLength] = {2.0,   2.0,   3.0,  3.0,  -0.0,
+                                       -0.0,  finf,  finf, 42.0, 42.0,
+                                       fminf, fminf, fnan};
+    float outputsfmax[kTableLength] = {3.0,  3.0,  3.0,  3.0,  0.0,  0.0, finf,
+                                       finf, finf, finf, finf, finf, fnan};
 
     __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
     __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b)));
@@ -1863,16 +1877,20 @@
 
 TEST(mina_maxa) {
   if (IsMipsArchVariant(kMips32r6)) {
-    const int kTableLength = 15;
+    const int kTableLength = 23;
     CcTest::InitializeVM();
     Isolate* isolate = CcTest::i_isolate();
     HandleScope scope(isolate);
-    MacroAssembler assm(isolate, NULL, 0,
+    MacroAssembler assm(isolate, nullptr, 0,
                         v8::internal::CodeObjectRequired::kYes);
-    const double double_nan = std::numeric_limits<double>::quiet_NaN();
-    const float  float_nan = std::numeric_limits<float>::quiet_NaN();
+    const double dnan = std::numeric_limits<double>::quiet_NaN();
+    const double dinf = std::numeric_limits<double>::infinity();
+    const double dminf = -std::numeric_limits<double>::infinity();
+    const float fnan = std::numeric_limits<float>::quiet_NaN();
+    const float finf = std::numeric_limits<float>::infinity();
+    const float fminf = std::numeric_limits<float>::infinity();
 
-    typedef struct test_float {
+    struct TestFloat {
       double a;
       double b;
       double resd;
@@ -1881,41 +1899,34 @@
       float d;
       float resf;
       float resf1;
-    }TestFloat;
+    };
 
     TestFloat test;
     double inputsa[kTableLength] = {
-      5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
-      -9.8, -10.0, -8.9, -9.8, double_nan, 3.0, double_nan
-    };
+        5.3,  4.8, 6.1,  9.8, 9.8,  9.8,  -10.0, -8.9, -9.8,  -10.0, -8.9, -9.8,
+        dnan, 3.0, -0.0, 0.0, dinf, dnan, 42.0,  dinf, dminf, dinf,  dnan};
     double inputsb[kTableLength] = {
-      4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
-      9.8, -9.8, -11.2, -9.8, 3.0, double_nan, double_nan
-    };
+        4.8, 5.3,  6.1, -10.0, -8.9, -9.8, 9.8,  9.8,  9.8,  -9.8,  -11.2, -9.8,
+        3.0, dnan, 0.0, -0.0,  dnan, dinf, dinf, 42.0, dinf, dminf, dnan};
     double resd[kTableLength] = {
-      4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
-      -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, double_nan
-    };
+        4.8, 4.8, 6.1,  9.8,  -8.9, -9.8, 9.8,  -8.9, -9.8,  -9.8,  -8.9, -9.8,
+        3.0, 3.0, -0.0, -0.0, dinf, dinf, 42.0, 42.0, dminf, dminf, dnan};
     double resd1[kTableLength] = {
-      5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
-      9.8, -10.0, -11.2, -9.8, 3.0, 3.0, double_nan
-    };
+        5.3, 5.3, 6.1, -10.0, 9.8,  9.8,  -10.0, 9.8,  9.8,  -10.0, -11.2, -9.8,
+        3.0, 3.0, 0.0, 0.0,   dinf, dinf, dinf,  dinf, dinf, dinf,  dnan};
     float inputsc[kTableLength] = {
-      5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
-      -9.8, -10.0, -8.9, -9.8, float_nan, 3.0, float_nan
-    };
-    float inputsd[kTableLength] = {
-      4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
-      9.8, -9.8, -11.2, -9.8, 3.0, float_nan, float_nan
-    };
+        5.3,  4.8, 6.1,  9.8, 9.8,  9.8,  -10.0, -8.9, -9.8,  -10.0, -8.9, -9.8,
+        fnan, 3.0, -0.0, 0.0, finf, fnan, 42.0,  finf, fminf, finf,  fnan};
+    float inputsd[kTableLength] = {4.8,  5.3,  6.1,  -10.0, -8.9,  -9.8,
+                                   9.8,  9.8,  9.8,  -9.8,  -11.2, -9.8,
+                                   3.0,  fnan, -0.0, 0.0,   fnan,  finf,
+                                   finf, 42.0, finf, fminf, fnan};
     float resf[kTableLength] = {
-      4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
-      -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, float_nan
-    };
+        4.8, 4.8, 6.1,  9.8,  -8.9, -9.8, 9.8,  -8.9, -9.8,  -9.8,  -8.9, -9.8,
+        3.0, 3.0, -0.0, -0.0, finf, finf, 42.0, 42.0, fminf, fminf, fnan};
     float resf1[kTableLength] = {
-      5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
-      9.8, -10.0, -11.2, -9.8, 3.0, 3.0, float_nan
-    };
+        5.3, 5.3, 6.1, -10.0, 9.8,  9.8,  -10.0, 9.8,  9.8,  -10.0, -11.2, -9.8,
+        3.0, 3.0, 0.0, 0.0,   finf, finf, finf,  finf, finf, finf,  fnan};
 
     __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
     __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
@@ -5024,8 +5035,7 @@
   }
 }
 
-
-uint64_t run_addiupc(int32_t imm19) {
+static uint32_t run_addiupc(int32_t imm19) {
   Isolate* isolate = CcTest::i_isolate();
   HandleScope scope(isolate);
 
@@ -5058,13 +5068,13 @@
       int32_t   imm19;
     };
 
-    struct TestCaseAddiupc tc[] = {
-      //  imm19
-      { -262144 },   // 0x40000
-      {      -1 },   // 0x7FFFF
-      {       0 },
-      {       1 },   // 0x00001
-      {  262143 }    // 0x3FFFF
+    TestCaseAddiupc tc[] = {
+        //  imm19
+        {-262144},  // 0x40000
+        {-1},       // 0x7FFFF
+        {0},
+        {1},      // 0x00001
+        {262143}  // 0x3FFFF
     };
 
     size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc);
diff --git a/test/cctest/test-assembler-mips64.cc b/test/cctest/test-assembler-mips64.cc
index 988083c..b979db2 100644
--- a/test/cctest/test-assembler-mips64.cc
+++ b/test/cctest/test-assembler-mips64.cc
@@ -1586,10 +1586,10 @@
     CcTest::InitializeVM();
     Isolate* isolate = CcTest::i_isolate();
     HandleScope scope(isolate);
-    MacroAssembler assm(isolate, NULL, 0,
+    MacroAssembler assm(isolate, nullptr, 0,
                         v8::internal::CodeObjectRequired::kYes);
 
-    typedef struct test_float {
+    struct TestFloat {
       double a;
       double b;
       double c;
@@ -1598,21 +1598,35 @@
       float f;
       float g;
       float h;
-    } TestFloat;
+    };
 
     TestFloat test;
-    const double double_nan = std::numeric_limits<double>::quiet_NaN();
-    const float  float_nan = std::numeric_limits<float>::quiet_NaN();
-    const int kTableLength = 5;
-    double inputsa[kTableLength] = {2.0, 3.0, double_nan, 3.0, double_nan};
-    double inputsb[kTableLength] = {3.0, 2.0, 3.0, double_nan, double_nan};
-    double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, double_nan};
-    double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, double_nan};
+    const double dnan = std::numeric_limits<double>::quiet_NaN();
+    const double dinf = std::numeric_limits<double>::infinity();
+    const double dminf = -std::numeric_limits<double>::infinity();
+    const float fnan = std::numeric_limits<float>::quiet_NaN();
+    const float finf = std::numeric_limits<float>::infinity();
+    const float fminf = std::numeric_limits<float>::infinity();
+    const int kTableLength = 13;
+    double inputsa[kTableLength] = {2.0,  3.0,  dnan, 3.0,   -0.0, 0.0, dinf,
+                                    dnan, 42.0, dinf, dminf, dinf, dnan};
+    double inputsb[kTableLength] = {3.0,  2.0,  3.0,  dnan, 0.0,   -0.0, dnan,
+                                    dinf, dinf, 42.0, dinf, dminf, dnan};
+    double outputsdmin[kTableLength] = {2.0,   2.0,   3.0,  3.0,  -0.0,
+                                        -0.0,  dinf,  dinf, 42.0, 42.0,
+                                        dminf, dminf, dnan};
+    double outputsdmax[kTableLength] = {3.0,  3.0,  3.0,  3.0,  0.0,  0.0, dinf,
+                                        dinf, dinf, dinf, dinf, dinf, dnan};
 
-    float inputse[kTableLength] = {2.0, 3.0, float_nan, 3.0, float_nan};
-    float inputsf[kTableLength] = {3.0, 2.0, 3.0, float_nan, float_nan};
-    float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, float_nan};
-    float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, float_nan};
+    float inputse[kTableLength] = {2.0,  3.0,  fnan, 3.0,   -0.0, 0.0, finf,
+                                   fnan, 42.0, finf, fminf, finf, fnan};
+    float inputsf[kTableLength] = {3.0,  2.0,  3.0,  fnan, -0.0,  0.0, fnan,
+                                   finf, finf, 42.0, finf, fminf, fnan};
+    float outputsfmin[kTableLength] = {2.0,   2.0,   3.0,  3.0,  -0.0,
+                                       -0.0,  finf,  finf, 42.0, 42.0,
+                                       fminf, fminf, fnan};
+    float outputsfmax[kTableLength] = {3.0,  3.0,  3.0,  3.0,  0.0,  0.0, finf,
+                                       finf, finf, finf, finf, finf, fnan};
 
     __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
     __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b)));
@@ -1946,16 +1960,20 @@
 
 TEST(mina_maxa) {
   if (kArchVariant == kMips64r6) {
-    const int kTableLength = 15;
+    const int kTableLength = 23;
     CcTest::InitializeVM();
     Isolate* isolate = CcTest::i_isolate();
     HandleScope scope(isolate);
-    MacroAssembler assm(isolate, NULL, 0,
+    MacroAssembler assm(isolate, nullptr, 0,
                         v8::internal::CodeObjectRequired::kYes);
-    const double double_nan = std::numeric_limits<double>::quiet_NaN();
-    const float  float_nan = std::numeric_limits<float>::quiet_NaN();
+    const double dnan = std::numeric_limits<double>::quiet_NaN();
+    const double dinf = std::numeric_limits<double>::infinity();
+    const double dminf = -std::numeric_limits<double>::infinity();
+    const float fnan = std::numeric_limits<float>::quiet_NaN();
+    const float finf = std::numeric_limits<float>::infinity();
+    const float fminf = std::numeric_limits<float>::infinity();
 
-    typedef struct test_float {
+    struct TestFloat {
       double a;
       double b;
       double resd;
@@ -1964,41 +1982,34 @@
       float d;
       float resf;
       float resf1;
-    }TestFloat;
+    };
 
     TestFloat test;
     double inputsa[kTableLength] = {
-      5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
-      -9.8, -10.0, -8.9, -9.8, double_nan, 3.0, double_nan
-    };
+        5.3,  4.8, 6.1,  9.8, 9.8,  9.8,  -10.0, -8.9, -9.8,  -10.0, -8.9, -9.8,
+        dnan, 3.0, -0.0, 0.0, dinf, dnan, 42.0,  dinf, dminf, dinf,  dnan};
     double inputsb[kTableLength] = {
-      4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
-      9.8, -9.8, -11.2, -9.8, 3.0, double_nan, double_nan
-    };
+        4.8, 5.3,  6.1, -10.0, -8.9, -9.8, 9.8,  9.8,  9.8,  -9.8,  -11.2, -9.8,
+        3.0, dnan, 0.0, -0.0,  dnan, dinf, dinf, 42.0, dinf, dminf, dnan};
     double resd[kTableLength] = {
-      4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
-      -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, double_nan
-    };
+        4.8, 4.8, 6.1,  9.8,  -8.9, -9.8, 9.8,  -8.9, -9.8,  -9.8,  -8.9, -9.8,
+        3.0, 3.0, -0.0, -0.0, dinf, dinf, 42.0, 42.0, dminf, dminf, dnan};
     double resd1[kTableLength] = {
-      5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
-      9.8, -10.0, -11.2, -9.8, 3.0, 3.0, double_nan
-    };
+        5.3, 5.3, 6.1, -10.0, 9.8,  9.8,  -10.0, 9.8,  9.8,  -10.0, -11.2, -9.8,
+        3.0, 3.0, 0.0, 0.0,   dinf, dinf, dinf,  dinf, dinf, dinf,  dnan};
     float inputsc[kTableLength] = {
-      5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
-      -9.8, -10.0, -8.9, -9.8, float_nan, 3.0, float_nan
-    };
-    float inputsd[kTableLength] = {
-      4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
-      9.8, -9.8, -11.2, -9.8, 3.0, float_nan, float_nan
-    };
+        5.3,  4.8, 6.1,  9.8, 9.8,  9.8,  -10.0, -8.9, -9.8,  -10.0, -8.9, -9.8,
+        fnan, 3.0, -0.0, 0.0, finf, fnan, 42.0,  finf, fminf, finf,  fnan};
+    float inputsd[kTableLength] = {4.8,  5.3,  6.1,  -10.0, -8.9,  -9.8,
+                                   9.8,  9.8,  9.8,  -9.8,  -11.2, -9.8,
+                                   3.0,  fnan, -0.0, 0.0,   fnan,  finf,
+                                   finf, 42.0, finf, fminf, fnan};
     float resf[kTableLength] = {
-      4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
-      -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, float_nan
-    };
+        4.8, 4.8, 6.1,  9.8,  -8.9, -9.8, 9.8,  -8.9, -9.8,  -9.8,  -8.9, -9.8,
+        3.0, 3.0, -0.0, -0.0, finf, finf, 42.0, 42.0, fminf, fminf, fnan};
     float resf1[kTableLength] = {
-      5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
-      9.8, -10.0, -11.2, -9.8, 3.0, 3.0, float_nan
-    };
+        5.3, 5.3, 6.1, -10.0, 9.8,  9.8,  -10.0, 9.8,  9.8,  -10.0, -11.2, -9.8,
+        3.0, 3.0, 0.0, 0.0,   finf, finf, finf,  finf, finf, finf,  fnan};
 
     __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
     __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
@@ -4997,6 +5008,55 @@
 }
 
 
+uint64_t run_li_macro(uint64_t rs, LiFlags mode) {
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+  MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
+
+  __ li(a0, rs, mode);
+  __ mov(v0, a0);
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+  F2 f = FUNCTION_CAST<F2>(code->entry());
+
+  uint64_t res = reinterpret_cast<uint64_t>(
+      CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
+
+  return res;
+}
+
+
+TEST(li_macro) {
+  CcTest::InitializeVM();
+
+  uint64_t inputs[] = {
+      0x0000000000000000, 0x000000000000ffff, 0x00000000ffffffff,
+      0x0000ffffffffffff, 0xffffffffffffffff, 0xffff000000000000,
+      0xffffffff00000000, 0xffffffffffff0000, 0xffff0000ffff0000,
+      0x0000ffffffff0000, 0x0000ffff0000ffff, 0x00007fffffffffff,
+      0x7fffffffffffffff, 0x000000007fffffff, 0x00007fff7fffffff,
+  };
+
+  size_t nr_test_cases = sizeof(inputs) / sizeof(inputs[0]);
+  for (size_t i = 0; i < nr_test_cases; ++i) {
+    uint64_t res = run_li_macro(inputs[i], OPTIMIZE_SIZE);
+    CHECK_EQ(inputs[i], res);
+    res = run_li_macro(inputs[i], CONSTANT_SIZE);
+    CHECK_EQ(inputs[i], res);
+    if (is_int48(inputs[i])) {
+      res = run_li_macro(inputs[i], ADDRESS_LOAD);
+      CHECK_EQ(inputs[i], res);
+    }
+  }
+}
+
+
 uint64_t run_lwpc(int offset) {
   Isolate* isolate = CcTest::i_isolate();
   HandleScope scope(isolate);
diff --git a/test/cctest/test-ast-expression-visitor.cc b/test/cctest/test-ast-expression-visitor.cc
index b6cca6a..a40f87c 100644
--- a/test/cctest/test-ast-expression-visitor.cc
+++ b/test/cctest/test-ast-expression-visitor.cc
@@ -343,7 +343,6 @@
   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"
       "  throw 123;\n"
@@ -364,7 +363,6 @@
   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"
       "  yield 123;\n"
@@ -372,7 +370,7 @@
   CollectTypes(&handles, test_function, &types);
   CHECK_TYPES_BEGIN {
     CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
-      // Generator function yields generator on entry.
+      // Implicit initial yield
       CHECK_EXPR(Yield, Bounds::Unbounded()) {
         CHECK_VAR(.generator_object, Bounds::Unbounded());
         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
@@ -380,16 +378,20 @@
           CHECK_EXPR(CallRuntime, Bounds::Unbounded());
         }
       }
-      // Then yields undefined.
+      // Explicit yield
       CHECK_EXPR(Yield, Bounds::Unbounded()) {
         CHECK_VAR(.generator_object, Bounds::Unbounded());
         CHECK_EXPR(Literal, Bounds::Unbounded());
       }
-      // Then yields 123.
+      // Implicit final yield
       CHECK_EXPR(Yield, Bounds::Unbounded()) {
         CHECK_VAR(.generator_object, Bounds::Unbounded());
         CHECK_EXPR(Literal, Bounds::Unbounded());
       }
+      // Implicit finally clause
+      CHECK_EXPR(CallRuntime, Bounds::Unbounded()) {
+        CHECK_VAR(.generator_object, Bounds::Unbounded());
+      }
     }
   }
   CHECK_TYPES_END
@@ -400,7 +402,6 @@
   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(x) {\n"
       "  return (x + x) + 1;\n"
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 29a24e6..361c879 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -75,7 +75,7 @@
   CpuProfilesCollection profiles(isolate->heap());
   ProfileGenerator generator(&profiles);
   SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
-          &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
+      &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
   processor->Start();
   processor->StopSynchronously();
 }
@@ -417,15 +417,16 @@
   CHECK(profile->GetStartTime() <= profile->GetEndTime());
 }
 
-
 static v8::CpuProfile* RunProfiler(v8::Local<v8::Context> env,
                                    v8::Local<v8::Function> function,
                                    v8::Local<v8::Value> argv[], int argc,
-                                   unsigned min_js_samples,
+                                   unsigned min_js_samples = 0,
+                                   unsigned min_external_samples = 0,
                                    bool collect_samples = false) {
   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
   v8::Local<v8::String> profile_name = v8_str("my_profile");
 
+  cpu_profiler->SetSamplingInterval(100);
   cpu_profiler->StartProfiling(profile_name, collect_samples);
 
   i::Sampler* sampler =
@@ -433,7 +434,8 @@
   sampler->StartCountingSamples();
   do {
     function->Call(env, env->Global(), argc, argv).ToLocalChecked();
-  } while (sampler->js_and_external_sample_count() < min_js_samples);
+  } while (sampler->js_sample_count() < min_js_samples ||
+           sampler->external_sample_count() < min_external_samples);
 
   v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
 
@@ -445,55 +447,14 @@
 }
 
 
-static bool ContainsString(v8::Local<v8::Context> context,
-                           v8::Local<v8::String> string,
-                           const Vector<v8::Local<v8::String> >& vector) {
-  for (int i = 0; i < vector.length(); i++) {
-    if (string->Equals(context, vector[i]).FromJust()) return true;
-  }
-  return false;
-}
-
-
-static void CheckChildrenNames(v8::Local<v8::Context> context,
-                               const v8::CpuProfileNode* node,
-                               const Vector<v8::Local<v8::String> >& names) {
-  int count = node->GetChildrenCount();
-  for (int i = 0; i < count; i++) {
-    v8::Local<v8::String> name = node->GetChild(i)->GetFunctionName();
-    if (!ContainsString(context, name, names)) {
-      char buffer[100];
-      i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
-                  "Unexpected child '%s' found in '%s'",
-                  *v8::String::Utf8Value(name),
-                  *v8::String::Utf8Value(node->GetFunctionName()));
-      FATAL(buffer);
-    }
-    // Check that there are no duplicates.
-    for (int j = 0; j < count; j++) {
-      if (j == i) continue;
-      if (name->Equals(context, node->GetChild(j)->GetFunctionName())
-              .FromJust()) {
-        char buffer[100];
-        i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
-                    "Second child with the same name '%s' found in '%s'",
-                    *v8::String::Utf8Value(name),
-                    *v8::String::Utf8Value(node->GetFunctionName()));
-        FATAL(buffer);
-      }
-    }
-  }
-}
-
-
 static const v8::CpuProfileNode* FindChild(v8::Local<v8::Context> context,
                                            const v8::CpuProfileNode* node,
                                            const char* name) {
   int count = node->GetChildrenCount();
-  v8::Local<v8::String> nameHandle = v8_str(name);
+  v8::Local<v8::String> name_handle = v8_str(name);
   for (int i = 0; i < count; i++) {
     const v8::CpuProfileNode* child = node->GetChild(i);
-    if (nameHandle->Equals(context, child->GetFunctionName()).FromJust()) {
+    if (name_handle->Equals(context, child->GetFunctionName()).FromJust()) {
       return child;
     }
   }
@@ -521,8 +482,6 @@
   for (int i = 0; i < length; i++) {
     const char* name = names[i];
     node = GetChild(context, node, name);
-    int expectedChildrenCount = (i == length - 1) ? 0 : 1;
-    CHECK_EQ(expectedChildrenCount, node->GetChildrenCount());
   }
 }
 
@@ -537,38 +496,43 @@
   return reinterpret_cast<const ProfileNode*>(node);
 }
 
+static void CallCollectSample(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  info.GetIsolate()->GetCpuProfiler()->CollectSample();
+}
 
-static const char* cpu_profiler_test_source = "function loop(timeout) {\n"
-"  this.mmm = 0;\n"
-"  var start = Date.now();\n"
-"  while (Date.now() - start < timeout) {\n"
-"    var n = 100*1000;\n"
-"    while(n > 1) {\n"
-"      n--;\n"
-"      this.mmm += n * n * n;\n"
-"    }\n"
-"  }\n"
-"}\n"
-"function delay() { try { loop(10); } catch(e) { } }\n"
-"function bar() { delay(); }\n"
-"function baz() { delay(); }\n"
-"function foo() {\n"
-"    try {\n"
-"       delay();\n"
-"       bar();\n"
-"       delay();\n"
-"       baz();\n"
-"    } catch (e) { }\n"
-"}\n"
-"function start(timeout) {\n"
-"  var start = Date.now();\n"
-"  do {\n"
-"    foo();\n"
-"    var duration = Date.now() - start;\n"
-"  } while (duration < timeout);\n"
-"  return duration;\n"
-"}\n";
-
+static const char* cpu_profiler_test_source =
+    "%NeverOptimizeFunction(loop);\n"
+    "%NeverOptimizeFunction(delay);\n"
+    "%NeverOptimizeFunction(bar);\n"
+    "%NeverOptimizeFunction(baz);\n"
+    "%NeverOptimizeFunction(foo);\n"
+    "%NeverOptimizeFunction(start);\n"
+    "function loop(timeout) {\n"
+    "  this.mmm = 0;\n"
+    "  var start = Date.now();\n"
+    "  do {\n"
+    "    var n = 1000;\n"
+    "    while(n > 1) {\n"
+    "      n--;\n"
+    "      this.mmm += n * n * n;\n"
+    "    }\n"
+    "  } while (Date.now() - start < timeout);\n"
+    "}\n"
+    "function delay() { loop(10); }\n"
+    "function bar() { delay(); }\n"
+    "function baz() { delay(); }\n"
+    "function foo() {\n"
+    "  delay();\n"
+    "  bar();\n"
+    "  delay();\n"
+    "  baz();\n"
+    "}\n"
+    "function start(duration) {\n"
+    "  var start = Date.now();\n"
+    "  do {\n"
+    "    foo();\n"
+    "  } while (Date.now() - start < duration);\n"
+    "}\n";
 
 // Check that the profile tree for the script above will look like the
 // following:
@@ -588,6 +552,7 @@
 //     2     2    (program) [-1]
 //     6     6    (garbage collector) [-1]
 TEST(CollectCpuProfile) {
+  i::FLAG_allow_natives_syntax = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -598,49 +563,37 @@
   v8::Local<v8::Value> args[] = {
       v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 200);
-  function->Call(env.local(), env->Global(), arraysize(args), args)
-      .ToLocalChecked();
+      RunProfiler(env.local(), function, args, arraysize(args), 1000);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+  const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+  const v8::CpuProfileNode* foo_node = GetChild(env.local(), start_node, "foo");
 
-  ScopedVector<v8::Local<v8::String> > names(3);
-  names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-  names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-  names[2] = v8_str("start");
-  CheckChildrenNames(env.local(), root, names);
-
-  const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
-  CHECK_EQ(1, startNode->GetChildrenCount());
-
-  const v8::CpuProfileNode* fooNode = GetChild(env.local(), startNode, "foo");
-  CHECK_EQ(3, fooNode->GetChildrenCount());
-
-  const char* barBranch[] = { "bar", "delay", "loop" };
-  CheckSimpleBranch(env.local(), fooNode, barBranch, arraysize(barBranch));
-  const char* bazBranch[] = { "baz", "delay", "loop" };
-  CheckSimpleBranch(env.local(), fooNode, bazBranch, arraysize(bazBranch));
-  const char* delayBranch[] = { "delay", "loop" };
-  CheckSimpleBranch(env.local(), fooNode, delayBranch, arraysize(delayBranch));
+  const char* bar_branch[] = {"bar", "delay", "loop"};
+  CheckSimpleBranch(env.local(), foo_node, bar_branch, arraysize(bar_branch));
+  const char* baz_branch[] = {"baz", "delay", "loop"};
+  CheckSimpleBranch(env.local(), foo_node, baz_branch, arraysize(baz_branch));
+  const char* delay_branch[] = {"delay", "loop"};
+  CheckSimpleBranch(env.local(), foo_node, delay_branch,
+                    arraysize(delay_branch));
 
   profile->Delete();
 }
 
-
 static const char* hot_deopt_no_frame_entry_test_source =
-"function foo(a, b) {\n"
-"    try {\n"
-"      return a + b;\n"
-"    } catch (e) { }\n"
-"}\n"
-"function start(timeout) {\n"
-"  var start = Date.now();\n"
-"  do {\n"
-"    for (var i = 1; i < 1000; ++i) foo(1, i);\n"
-"    var duration = Date.now() - start;\n"
-"  } while (duration < timeout);\n"
-"  return duration;\n"
-"}\n";
+    "%NeverOptimizeFunction(foo);\n"
+    "%NeverOptimizeFunction(start);\n"
+    "function foo(a, b) {\n"
+    "  return a + b;\n"
+    "}\n"
+    "function start(timeout) {\n"
+    "  var start = Date.now();\n"
+    "  do {\n"
+    "    for (var i = 1; i < 1000; ++i) foo(1, i);\n"
+    "    var duration = Date.now() - start;\n"
+    "  } while (duration < timeout);\n"
+    "  return duration;\n"
+    "}\n";
 
 // Check that the profile tree for the script above will look like the
 // following:
@@ -652,10 +605,11 @@
 //     2     2    (program) [-1]
 //     6     6    (garbage collector) [-1]
 //
-// The test checks no FP ranges are present in a deoptimized funcion.
+// The test checks no FP ranges are present in a deoptimized function.
 // If 'foo' has no ranges the samples falling into the prologue will miss the
 // 'start' function on the stack, so 'foo' will be attached to the (root).
 TEST(HotDeoptNoFrameEntry) {
+  i::FLAG_allow_natives_syntax = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -666,28 +620,19 @@
   v8::Local<v8::Value> args[] = {
       v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 200);
+      RunProfiler(env.local(), function, args, arraysize(args), 1000);
   function->Call(env.local(), env->Global(), arraysize(args), args)
       .ToLocalChecked();
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-
-  ScopedVector<v8::Local<v8::String> > names(3);
-  names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-  names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-  names[2] = v8_str("start");
-  CheckChildrenNames(env.local(), root, names);
-
-  const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
-  CHECK_EQ(1, startNode->GetChildrenCount());
-
-  GetChild(env.local(), startNode, "foo");
+  const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+  GetChild(env.local(), start_node, "foo");
 
   profile->Delete();
 }
 
-
 TEST(CollectCpuProfileSamples) {
+  i::FLAG_allow_natives_syntax = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -698,7 +643,7 @@
   v8::Local<v8::Value> args[] = {
       v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 200, true);
+      RunProfiler(env.local(), function, args, arraysize(args), 1000, 0, true);
 
   CHECK_LE(200, profile->GetSamplesCount());
   uint64_t end_time = profile->GetEndTime();
@@ -715,15 +660,18 @@
   profile->Delete();
 }
 
-
-static const char* cpu_profiler_test_source2 = "function loop() {}\n"
-"function delay() { loop(); }\n"
-"function start(count) {\n"
-"  var k = 0;\n"
-"  do {\n"
-"    delay();\n"
-"  } while (++k < count*100*1000);\n"
-"}\n";
+static const char* cpu_profiler_test_source2 =
+    "%NeverOptimizeFunction(loop);\n"
+    "%NeverOptimizeFunction(delay);\n"
+    "%NeverOptimizeFunction(start);\n"
+    "function loop() {}\n"
+    "function delay() { loop(); }\n"
+    "function start(duration) {\n"
+    "  var start = Date.now();\n"
+    "  do {\n"
+    "    for (var i = 0; i < 10000; ++i) delay();\n"
+    "  } while (Date.now() - start < duration);\n"
+    "}";
 
 // Check that the profile tree doesn't contain unexpected traces:
 //  - 'loop' can be called only by 'delay'
@@ -737,47 +685,28 @@
 //    16    16        loop [-1] #5
 //    14    14    (program) [-1] #2
 TEST(SampleWhenFrameIsNotSetup) {
+  i::FLAG_allow_natives_syntax = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
   CompileRun(cpu_profiler_test_source2);
   v8::Local<v8::Function> function = GetFunction(env.local(), "start");
 
-  int32_t repeat_count = 100;
-#if defined(USE_SIMULATOR)
-  // Simulators are much slower.
-  repeat_count = 1;
-#endif
+  int32_t duration_ms = 100;
   v8::Local<v8::Value> args[] = {
-      v8::Integer::New(env->GetIsolate(), repeat_count)};
+      v8::Integer::New(env->GetIsolate(), duration_ms)};
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 100);
+      RunProfiler(env.local(), function, args, arraysize(args), 1000);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-
-  ScopedVector<v8::Local<v8::String> > names(3);
-  names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-  names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-  names[2] = v8_str("start");
-  CheckChildrenNames(env.local(), root, names);
-
-  const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
-  // On slow machines there may be no meaningfull samples at all, skip the
-  // check there.
-  if (startNode && startNode->GetChildrenCount() > 0) {
-    CHECK_EQ(1, startNode->GetChildrenCount());
-    const v8::CpuProfileNode* delayNode =
-        GetChild(env.local(), startNode, "delay");
-    if (delayNode->GetChildrenCount() > 0) {
-      CHECK_EQ(1, delayNode->GetChildrenCount());
-      GetChild(env.local(), delayNode, "loop");
-    }
-  }
+  const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+  const v8::CpuProfileNode* delay_node =
+      GetChild(env.local(), start_node, "delay");
+  GetChild(env.local(), delay_node, "loop");
 
   profile->Delete();
 }
 
-
 static const char* native_accessor_test_source = "function start(count) {\n"
 "  for (var i = 0; i < count; i++) {\n"
 "    var o = instance.foo;\n"
@@ -785,7 +714,6 @@
 "  }\n"
 "}\n";
 
-
 class TestApiCallbacks {
  public:
   explicit TestApiCallbacks(int min_duration_ms)
@@ -794,19 +722,19 @@
 
   static void Getter(v8::Local<v8::String> name,
                      const v8::PropertyCallbackInfo<v8::Value>& info) {
-    TestApiCallbacks* data = fromInfo(info);
+    TestApiCallbacks* data = FromInfo(info);
     data->Wait();
   }
 
   static void Setter(v8::Local<v8::String> name,
                      v8::Local<v8::Value> value,
                      const v8::PropertyCallbackInfo<void>& info) {
-    TestApiCallbacks* data = fromInfo(info);
+    TestApiCallbacks* data = FromInfo(info);
     data->Wait();
   }
 
   static void Callback(const v8::FunctionCallbackInfo<v8::Value>& info) {
-    TestApiCallbacks* data = fromInfo(info);
+    TestApiCallbacks* data = FromInfo(info);
     data->Wait();
   }
 
@@ -823,8 +751,8 @@
     }
   }
 
-  template<typename T>
-  static TestApiCallbacks* fromInfo(const T& info) {
+  template <typename T>
+  static TestApiCallbacks* FromInfo(const T& info) {
     void* data = v8::External::Cast(*info.Data())->Value();
     return reinterpret_cast<TestApiCallbacks*>(data);
   }
@@ -865,12 +793,12 @@
   int32_t repeat_count = 1;
   v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 180);
+      RunProfiler(env.local(), function, args, arraysize(args), 0, 100);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
-  GetChild(env.local(), startNode, "get foo");
-  GetChild(env.local(), startNode, "set foo");
+  const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+  GetChild(env.local(), start_node, "get foo");
+  GetChild(env.local(), start_node, "set foo");
 
   profile->Delete();
 }
@@ -918,12 +846,12 @@
   int32_t repeat_count = 100;
   v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 200);
+      RunProfiler(env.local(), function, args, arraysize(args), 0, 100);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
-  GetChild(env.local(), startNode, "get foo");
-  GetChild(env.local(), startNode, "set foo");
+  const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+  GetChild(env.local(), start_node, "get foo");
+  GetChild(env.local(), start_node, "set foo");
 
   profile->Delete();
 }
@@ -969,11 +897,11 @@
   int32_t repeat_count = 1;
   v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 100);
+      RunProfiler(env.local(), function, args, arraysize(args), 0, 100);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
-  GetChild(env.local(), startNode, "fooMethod");
+  const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+  GetChild(env.local(), start_node, "fooMethod");
 
   profile->Delete();
 }
@@ -1023,12 +951,12 @@
   int32_t repeat_count = 100;
   v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 100);
+      RunProfiler(env.local(), function, args, arraysize(args), 0, 200);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
   GetChild(env.local(), root, "start");
-  const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
-  GetChild(env.local(), startNode, "fooMethod");
+  const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+  GetChild(env.local(), start_node, "fooMethod");
 
   profile->Delete();
 }
@@ -1052,18 +980,12 @@
   CompileRun(bound_function_test_source);
   v8::Local<v8::Function> function = GetFunction(env, "start");
 
-  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  ScopedVector<v8::Local<v8::String> > names(3);
-  names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-  names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-  names[2] = v8_str("start");
-  // Don't allow |foo| node to be at the top level.
-  CheckChildrenNames(env, root, names);
 
-  const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
-  GetChild(env, startNode, "foo");
+  const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+  GetChild(env, start_node, "foo");
 
   profile->Delete();
 }
@@ -1166,18 +1088,21 @@
   CHECK_EQ(hit_count, value);
 }
 
-
-static const char* call_function_test_source = "function bar(iterations) {\n"
-"}\n"
-"function start(duration) {\n"
-"  var start = Date.now();\n"
-"  while (Date.now() - start < duration) {\n"
-"    try {\n"
-"      bar.call(this, 10 * 1000);\n"
-"    } catch(e) {}\n"
-"  }\n"
-"}";
-
+static const char* call_function_test_source =
+    "%NeverOptimizeFunction(bar);\n"
+    "%NeverOptimizeFunction(start);\n"
+    "function bar(n) {\n"
+    "  var s = 0;\n"
+    "  for (var i = 0; i < n; i++) s += i * i * i;\n"
+    "  return s;\n"
+    "}\n"
+    "function start(duration) {\n"
+    "  var start = Date.now();\n"
+    "  do {\n"
+    "    for (var i = 0; i < 100; ++i)\n"
+    "      bar.call(this, 1000);\n"
+    "  } while (Date.now() - start < duration);\n"
+    "}";
 
 // Test that if we sampled thread when it was inside FunctionCall buitin then
 // its caller frame will be '(unresolved function)' as we have no reliable way
@@ -1192,6 +1117,7 @@
 //     1     1      bar [-1] #7
 //    19    19    (program) [-1] #2
 TEST(FunctionCallSample) {
+  i::FLAG_allow_natives_syntax = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -1206,60 +1132,38 @@
   v8::Local<v8::Value> args[] = {
       v8::Integer::New(env->GetIsolate(), duration_ms)};
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 100);
+      RunProfiler(env.local(), function, args, arraysize(args), 1000);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  {
-    ScopedVector<v8::Local<v8::String> > names(4);
-    names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-    names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-    names[2] = v8_str("start");
-    names[3] = v8_str(i::ProfileGenerator::kUnresolvedFunctionName);
-    // Don't allow |bar| and |call| nodes to be at the top level.
-    CheckChildrenNames(env.local(), root, names);
-  }
+  const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+  GetChild(env.local(), start_node, "bar");
 
-  // In case of GC stress tests all samples may be in GC phase and there
-  // won't be |start| node in the profiles.
-  bool is_gc_stress_testing =
-      (i::FLAG_gc_interval != -1) || i::FLAG_stress_compaction;
-  const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
-  CHECK(is_gc_stress_testing || startNode);
-  if (startNode) {
-    ScopedVector<v8::Local<v8::String> > names(2);
-    names[0] = v8_str("bar");
-    names[1] = v8_str("call");
-    CheckChildrenNames(env.local(), startNode, names);
-  }
-
-  const v8::CpuProfileNode* unresolvedNode = FindChild(
+  const v8::CpuProfileNode* unresolved_node = FindChild(
       env.local(), root, i::ProfileGenerator::kUnresolvedFunctionName);
-  if (unresolvedNode) {
-    ScopedVector<v8::Local<v8::String> > names(1);
-    names[0] = v8_str("call");
-    CheckChildrenNames(env.local(), unresolvedNode, names);
-  }
+  CHECK(!unresolved_node || GetChild(env.local(), unresolved_node, "call"));
 
   profile->Delete();
 }
 
-
 static const char* function_apply_test_source =
-    "function bar(iterations) {\n"
+    "%NeverOptimizeFunction(bar);\n"
+    "%NeverOptimizeFunction(test);\n"
+    "%NeverOptimizeFunction(start);\n"
+    "function bar(n) {\n"
+    "  var s = 0;\n"
+    "  for (var i = 0; i < n; i++) s += i * i * i;\n"
+    "  return s;\n"
     "}\n"
     "function test() {\n"
-    "  bar.apply(this, [10 * 1000]);\n"
+    "  bar.apply(this, [1000]);\n"
     "}\n"
     "function start(duration) {\n"
     "  var start = Date.now();\n"
-    "  while (Date.now() - start < duration) {\n"
-    "    try {\n"
-    "      test();\n"
-    "    } catch(e) {}\n"
-    "  }\n"
+    "  do {\n"
+    "    for (var i = 0; i < 100; ++i) test();\n"
+    "  } while (Date.now() - start < duration);\n"
     "}";
 
-
 // [Top down]:
 //    94     0   (root) [-1] #0 1
 //     2     2    (garbage collector) [-1] #0 7
@@ -1268,9 +1172,9 @@
 //     1     1        apply [-1] #0 9
 //    32    21      test [-1] #16 4
 //     2     2        bar [-1] #16 6
-//     9     9        apply [-1] #0 5
 //    10    10    (program) [-1] #0 2
 TEST(FunctionApplySample) {
+  i::FLAG_allow_natives_syntax = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -1282,64 +1186,32 @@
       v8::Integer::New(env->GetIsolate(), duration_ms)};
 
   v8::CpuProfile* profile =
-      RunProfiler(env.local(), function, args, arraysize(args), 100);
+      RunProfiler(env.local(), function, args, arraysize(args), 1000);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  {
-    ScopedVector<v8::Local<v8::String> > names(3);
-    names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-    names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-    names[2] = v8_str("start");
-    // Don't allow |test|, |bar| and |apply| nodes to be at the top level.
-    CheckChildrenNames(env.local(), root, names);
-  }
+  const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+  const v8::CpuProfileNode* test_node =
+      GetChild(env.local(), start_node, "test");
+  GetChild(env.local(), test_node, "bar");
 
-  const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
-  if (startNode) {
-    {
-      ScopedVector<v8::Local<v8::String> > names(2);
-      names[0] = v8_str("test");
-      names[1] = v8_str(ProfileGenerator::kUnresolvedFunctionName);
-      CheckChildrenNames(env.local(), startNode, names);
-    }
-
-    const v8::CpuProfileNode* testNode =
-        FindChild(env.local(), startNode, "test");
-    if (testNode) {
-      ScopedVector<v8::Local<v8::String> > names(3);
-      names[0] = v8_str("bar");
-      names[1] = v8_str("apply");
-      // apply calls "get length" before invoking the function itself
-      // and we may get hit into it.
-      names[2] = v8_str("get length");
-      CheckChildrenNames(env.local(), testNode, names);
-    }
-
-    if (const v8::CpuProfileNode* unresolvedNode =
-            FindChild(env.local(), startNode,
-                      ProfileGenerator::kUnresolvedFunctionName)) {
-      ScopedVector<v8::Local<v8::String> > names(1);
-      names[0] = v8_str("apply");
-      CheckChildrenNames(env.local(), unresolvedNode, names);
-      GetChild(env.local(), unresolvedNode, "apply");
-    }
-  }
+  const v8::CpuProfileNode* unresolved_node = FindChild(
+      env.local(), start_node, ProfileGenerator::kUnresolvedFunctionName);
+  CHECK(!unresolved_node || GetChild(env.local(), unresolved_node, "apply"));
 
   profile->Delete();
 }
 
-
 static const char* cpu_profiler_deep_stack_test_source =
-"function foo(n) {\n"
-"  if (n)\n"
-"    foo(n - 1);\n"
-"  else\n"
-"    startProfiling('my_profile');\n"
-"}\n"
-"function start() {\n"
-"  foo(250);\n"
-"}\n";
-
+    "function foo(n) {\n"
+    "  if (n)\n"
+    "    foo(n - 1);\n"
+    "  else\n"
+    "    collectSample();\n"
+    "}\n"
+    "function start() {\n"
+    "  startProfiling('my_profile');\n"
+    "  foo(250);\n"
+    "}\n";
 
 // Check a deep stack
 //
@@ -1350,8 +1222,7 @@
 //    0      foo 21 #4 no reason
 //    0        foo 21 #5 no reason
 //                ....
-//    0          foo 21 #253 no reason
-//    1            startProfiling 0 #254
+//    0          foo 21 #254 no reason
 TEST(CpuProfileDeepStack) {
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
@@ -1369,37 +1240,29 @@
   reinterpret_cast<i::CpuProfile*>(profile)->Print();
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  {
-    ScopedVector<v8::Local<v8::String> > names(3);
-    names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-    names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-    names[2] = v8_str("start");
-    CheckChildrenNames(env, root, names);
-  }
-
   const v8::CpuProfileNode* node = GetChild(env, root, "start");
-  for (int i = 0; i < 250; ++i) {
+  for (int i = 0; i <= 250; ++i) {
     node = GetChild(env, node, "foo");
   }
-  // TODO(alph):
-  // In theory there must be one more 'foo' and a 'startProfiling' nodes,
-  // but due to unstable top frame extraction these might be missing.
+  CHECK(!FindChild(env, node, "foo"));
 
   profile->Delete();
 }
 
-
 static const char* js_native_js_test_source =
-    "function foo() {\n"
-    "  startProfiling('my_profile');\n"
+    "%NeverOptimizeFunction(foo);\n"
+    "%NeverOptimizeFunction(bar);\n"
+    "%NeverOptimizeFunction(start);\n"
+    "function foo(n) {\n"
+    "  var s = 0;\n"
+    "  for (var i = 0; i < n; i++) s += i * i * i;\n"
+    "  return s;\n"
     "}\n"
     "function bar() {\n"
-    "  try { foo(); } catch(e) {}\n"
+    "  foo(1000);\n"
     "}\n"
     "function start() {\n"
-    "  try {\n"
-    "    CallJsFunction(bar);\n"
-    "  } catch(e) {}\n"
+    "  CallJsFunction(bar);\n"
     "}";
 
 static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -1410,7 +1273,6 @@
       .ToLocalChecked();
 }
 
-
 // [Top down]:
 //    58     0   (root) #0 1
 //     2     2    (program) #0 2
@@ -1419,6 +1281,7 @@
 //    55     1        bar #16 5
 //    54    54          foo #16 6
 TEST(JsNativeJsSample) {
+  i::FLAG_allow_natives_syntax = true;
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
   v8::Context::Scope context_scope(env);
@@ -1433,47 +1296,35 @@
   CompileRun(js_native_js_test_source);
   v8::Local<v8::Function> function = GetFunction(env, "start");
 
-  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  {
-    ScopedVector<v8::Local<v8::String> > names(3);
-    names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-    names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-    names[2] = v8_str("start");
-    CheckChildrenNames(env, root, names);
-  }
-
-  const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
-  CHECK_EQ(1, startNode->GetChildrenCount());
-  const v8::CpuProfileNode* nativeFunctionNode =
-      GetChild(env, startNode, "CallJsFunction");
-
-  CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
-  const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar");
-
-  CHECK_EQ(1, barNode->GetChildrenCount());
-  GetChild(env, barNode, "foo");
+  const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+  const v8::CpuProfileNode* native_node =
+      GetChild(env, start_node, "CallJsFunction");
+  const v8::CpuProfileNode* bar_node = GetChild(env, native_node, "bar");
+  GetChild(env, bar_node, "foo");
 
   profile->Delete();
 }
 
-
 static const char* js_native_js_runtime_js_test_source =
-    "function foo() {\n"
-    "  startProfiling('my_profile');\n"
+    "%NeverOptimizeFunction(foo);\n"
+    "%NeverOptimizeFunction(bar);\n"
+    "%NeverOptimizeFunction(start);\n"
+    "function foo(n) {\n"
+    "  var s = 0;\n"
+    "  for (var i = 0; i < n; i++) s += i * i * i;\n"
+    "  return s;\n"
     "}\n"
     "var bound = foo.bind(this);\n"
     "function bar() {\n"
-    "  try { bound(); } catch(e) {}\n"
+    "  bound(1000);\n"
     "}\n"
     "function start() {\n"
-    "  try {\n"
-    "    CallJsFunction(bar);\n"
-    "  } catch(e) {}\n"
+    "  CallJsFunction(bar);\n"
     "}";
 
-
 // [Top down]:
 //    57     0   (root) #0 1
 //    55     1    start #16 3
@@ -1482,6 +1333,7 @@
 //    51    51          foo #16 6
 //     2     2    (program) #0 2
 TEST(JsNativeJsRuntimeJsSample) {
+  i::FLAG_allow_natives_syntax = true;
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
   v8::Context::Scope context_scope(env);
@@ -1495,57 +1347,39 @@
 
   CompileRun(js_native_js_runtime_js_test_source);
   v8::Local<v8::Function> function = GetFunction(env, "start");
-
-  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  ScopedVector<v8::Local<v8::String> > names(3);
-  names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-  names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-  names[2] = v8_str("start");
-  CheckChildrenNames(env, root, names);
-
-  const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
-  CHECK_EQ(1, startNode->GetChildrenCount());
-  const v8::CpuProfileNode* nativeFunctionNode =
-      GetChild(env, startNode, "CallJsFunction");
-
-  CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
-  const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar");
-
-  // The child is in fact a bound foo.
-  // A bound function has a wrapper that may make calls to
-  // other functions e.g. "get length".
-  CHECK_LE(1, barNode->GetChildrenCount());
-  CHECK_GE(2, barNode->GetChildrenCount());
-  GetChild(env, barNode, "foo");
+  const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+  const v8::CpuProfileNode* native_node =
+      GetChild(env, start_node, "CallJsFunction");
+  const v8::CpuProfileNode* bar_node = GetChild(env, native_node, "bar");
+  GetChild(env, bar_node, "foo");
 
   profile->Delete();
 }
 
-
 static void CallJsFunction2(const v8::FunctionCallbackInfo<v8::Value>& info) {
   v8::base::OS::Print("In CallJsFunction2\n");
   CallJsFunction(info);
 }
 
-
 static const char* js_native1_js_native2_js_test_source =
+    "%NeverOptimizeFunction(foo);\n"
+    "%NeverOptimizeFunction(bar);\n"
+    "%NeverOptimizeFunction(start);\n"
     "function foo() {\n"
-    "  try {\n"
-    "    startProfiling('my_profile');\n"
-    "  } catch(e) {}\n"
+    "  var s = 0;\n"
+    "  for (var i = 0; i < 1000; i++) s += i * i * i;\n"
+    "  return s;\n"
     "}\n"
     "function bar() {\n"
     "  CallJsFunction2(foo);\n"
     "}\n"
     "function start() {\n"
-    "  try {\n"
-    "    CallJsFunction1(bar);\n"
-    "  } catch(e) {}\n"
+    "  CallJsFunction1(bar);\n"
     "}";
 
-
 // [Top down]:
 //    57     0   (root) #0 1
 //    55     1    start #16 3
@@ -1555,14 +1389,15 @@
 //    54    54            foo #16 7
 //     2     2    (program) #0 2
 TEST(JsNative1JsNative2JsSample) {
+  i::FLAG_allow_natives_syntax = true;
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
   v8::Context::Scope context_scope(env);
 
-  v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
-      env->GetIsolate(), CallJsFunction);
   v8::Local<v8::Function> func1 =
-      func_template->GetFunction(env).ToLocalChecked();
+      v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction)
+          ->GetFunction(env)
+          .ToLocalChecked();
   func1->SetName(v8_str("CallJsFunction1"));
   env->Global()->Set(env, v8_str("CallJsFunction1"), func1).FromJust();
 
@@ -1576,38 +1411,109 @@
   CompileRun(js_native1_js_native2_js_test_source);
   v8::Local<v8::Function> function = GetFunction(env, "start");
 
-  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  ScopedVector<v8::Local<v8::String> > names(3);
-  names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-  names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-  names[2] = v8_str("start");
-  CheckChildrenNames(env, root, names);
-
-  const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
-  CHECK_EQ(1, startNode->GetChildrenCount());
-  const v8::CpuProfileNode* nativeNode1 =
-      GetChild(env, startNode, "CallJsFunction1");
-
-  CHECK_EQ(1, nativeNode1->GetChildrenCount());
-  const v8::CpuProfileNode* barNode = GetChild(env, nativeNode1, "bar");
-
-  CHECK_EQ(1, barNode->GetChildrenCount());
-  const v8::CpuProfileNode* nativeNode2 =
-      GetChild(env, barNode, "CallJsFunction2");
-
-  CHECK_EQ(1, nativeNode2->GetChildrenCount());
-  GetChild(env, nativeNode2, "foo");
+  const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+  const v8::CpuProfileNode* native_node1 =
+      GetChild(env, start_node, "CallJsFunction1");
+  const v8::CpuProfileNode* bar_node = GetChild(env, native_node1, "bar");
+  const v8::CpuProfileNode* native_node2 =
+      GetChild(env, bar_node, "CallJsFunction2");
+  GetChild(env, native_node2, "foo");
 
   profile->Delete();
 }
 
+static const char* js_force_collect_sample_source =
+    "function start() {\n"
+    "  CallCollectSample();\n"
+    "}";
+
+TEST(CollectSampleAPI) {
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
+
+  v8::Local<v8::FunctionTemplate> func_template =
+      v8::FunctionTemplate::New(env->GetIsolate(), CallCollectSample);
+  v8::Local<v8::Function> func =
+      func_template->GetFunction(env).ToLocalChecked();
+  func->SetName(v8_str("CallCollectSample"));
+  env->Global()->Set(env, v8_str("CallCollectSample"), func).FromJust();
+
+  CompileRun(js_force_collect_sample_source);
+  v8::Local<v8::Function> function = GetFunction(env, "start");
+  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+
+  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+  const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+  CHECK_LE(1, start_node->GetChildrenCount());
+  GetChild(env, start_node, "CallCollectSample");
+
+  profile->Delete();
+}
+
+static const char* js_native_js_runtime_multiple_test_source =
+    "%NeverOptimizeFunction(foo);\n"
+    "%NeverOptimizeFunction(bar);\n"
+    "%NeverOptimizeFunction(start);\n"
+    "function foo() {\n"
+    "  return Math.sin(Math.random());\n"
+    "}\n"
+    "var bound = foo.bind(this);\n"
+    "function bar() {\n"
+    "  return bound();\n"
+    "}\n"
+    "function start() {\n"
+    "  startProfiling('my_profile');\n"
+    "  var startTime = Date.now();\n"
+    "  do {\n"
+    "    CallJsFunction(bar);\n"
+    "  } while (Date.now() - startTime < 200);\n"
+    "}";
+
+// The test check multiple entrances/exits between JS and native code.
+//
+// [Top down]:
+//    (root) #0 1
+//      start #16 3
+//        CallJsFunction #0 4
+//          bar #16 5
+//            foo #16 6
+//      (program) #0 2
+TEST(JsNativeJsRuntimeJsSampleMultiple) {
+  i::FLAG_allow_natives_syntax = true;
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
+
+  v8::Local<v8::FunctionTemplate> func_template =
+      v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction);
+  v8::Local<v8::Function> func =
+      func_template->GetFunction(env).ToLocalChecked();
+  func->SetName(v8_str("CallJsFunction"));
+  env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust();
+
+  CompileRun(js_native_js_runtime_multiple_test_source);
+  v8::Local<v8::Function> function = GetFunction(env, "start");
+
+  v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 500, 500);
+
+  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+  const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+  const v8::CpuProfileNode* native_node =
+      GetChild(env, start_node, "CallJsFunction");
+  const v8::CpuProfileNode* bar_node = GetChild(env, native_node, "bar");
+  GetChild(env, bar_node, "foo");
+
+  profile->Delete();
+}
 
 // [Top down]:
-//     6     0   (root) #0 1
-//     3     3    (program) #0 2
-//     3     3    (idle) #0 3
+//     0   (root) #0 1
+//     2    (program) #0 2
+//     3    (idle) #0 3
 TEST(IdleTime) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -1618,17 +1524,14 @@
 
   i::Isolate* isolate = CcTest::i_isolate();
   i::ProfilerEventsProcessor* processor = isolate->cpu_profiler()->processor();
-  processor->AddCurrentStack(isolate);
 
+  processor->AddCurrentStack(isolate, true);
   cpu_profiler->SetIdle(true);
-
   for (int i = 0; i < 3; i++) {
-    processor->AddCurrentStack(isolate);
+    processor->AddCurrentStack(isolate, true);
   }
-
   cpu_profiler->SetIdle(false);
-  processor->AddCurrentStack(isolate);
-
+  processor->AddCurrentStack(isolate, true);
 
   v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
   CHECK(profile);
@@ -1636,26 +1539,19 @@
   reinterpret_cast<i::CpuProfile*>(profile)->Print();
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-  ScopedVector<v8::Local<v8::String> > names(3);
-  names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
-  names[1] = v8_str(ProfileGenerator::kProgramEntryName);
-  names[2] = v8_str(ProfileGenerator::kIdleEntryName);
-  CheckChildrenNames(env.local(), root, names);
-
-  const v8::CpuProfileNode* programNode =
+  const v8::CpuProfileNode* program_node =
       GetChild(env.local(), root, ProfileGenerator::kProgramEntryName);
-  CHECK_EQ(0, programNode->GetChildrenCount());
-  CHECK_GE(programNode->GetHitCount(), 3u);
+  CHECK_EQ(0, program_node->GetChildrenCount());
+  CHECK_GE(program_node->GetHitCount(), 2u);
 
-  const v8::CpuProfileNode* idleNode =
+  const v8::CpuProfileNode* idle_node =
       GetChild(env.local(), root, ProfileGenerator::kIdleEntryName);
-  CHECK_EQ(0, idleNode->GetChildrenCount());
-  CHECK_GE(idleNode->GetHitCount(), 3u);
+  CHECK_EQ(0, idle_node->GetChildrenCount());
+  CHECK_GE(idle_node->GetHitCount(), 3u);
 
   profile->Delete();
 }
 
-
 static void CheckFunctionDetails(v8::Isolate* isolate,
                                  const v8::CpuProfileNode* node,
                                  const char* name, const char* script_name,
@@ -1672,17 +1568,21 @@
 
 
 TEST(FunctionDetails) {
+  i::FLAG_allow_natives_syntax = true;
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
   v8::Context::Scope context_scope(env);
 
   v8::Local<v8::Script> script_a = CompileWithOrigin(
-      "    function foo\n() { try { bar(); } catch(e) {} }\n"
+      "%NeverOptimizeFunction(foo);\n"
+      "%NeverOptimizeFunction(bar);\n"
+      "    function foo\n() { bar(); }\n"
       " function bar() { startProfiling(); }\n",
       "script_a");
   script_a->Run(env).ToLocalChecked();
   v8::Local<v8::Script> script_b = CompileWithOrigin(
-      "\n\n   function baz() { try { foo(); } catch(e) {} }\n"
+      "%NeverOptimizeFunction(baz);"
+      "\n\n   function baz() { foo(); }\n"
       "\n\nbaz();\n"
       "stopProfiling();\n",
       "script_b");
@@ -1706,10 +1606,10 @@
                        script_b->GetUnboundScript()->GetId(), 3, 16);
   const v8::CpuProfileNode* foo = GetChild(env, baz, "foo");
   CheckFunctionDetails(env->GetIsolate(), foo, "foo", "script_a",
-                       script_a->GetUnboundScript()->GetId(), 2, 1);
+                       script_a->GetUnboundScript()->GetId(), 4, 1);
   const v8::CpuProfileNode* bar = GetChild(env, foo, "bar");
   CheckFunctionDetails(env->GetIsolate(), bar, "bar", "script_a",
-                       script_a->GetUnboundScript()->GetId(), 3, 14);
+                       script_a->GetUnboundScript()->GetId(), 5, 14);
 }
 
 
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 914bda1..dd483c0 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -302,18 +302,6 @@
 }
 
 
-static void ChangeScriptBreakPointIgnoreCountFromJS(v8::Isolate* isolate,
-                                                    int break_point_number,
-                                                    int ignoreCount) {
-  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
-  SNPrintF(buffer,
-           "debug.Debug.changeScriptBreakPointIgnoreCount(%d, %d)",
-           break_point_number, ignoreCount);
-  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
-  CompileRunChecked(isolate, buffer.start());
-}
-
-
 // Change break on exception.
 static void ChangeBreakOnException(bool caught, bool uncaught) {
   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
@@ -1717,72 +1705,6 @@
 }
 
 
-// Test ignore count on script break points.
-TEST(ScriptBreakPointIgnoreCount) {
-  break_point_hit_count = 0;
-  DebugLocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  env.ExposeDebug();
-
-  v8::Debug::SetDebugEventListener(env->GetIsolate(),
-                                   DebugEventBreakPointHitCount);
-
-  v8::Local<v8::String> script = v8_str(env->GetIsolate(),
-                                        "function f() {\n"
-                                        "  a = 0;  // line 1\n"
-                                        "};");
-
-  // Compile the script and get function f.
-  v8::Local<v8::Context> context = env.context();
-  v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str(env->GetIsolate(), "test"));
-  v8::Script::Compile(context, script, &origin)
-      .ToLocalChecked()
-      ->Run(context)
-      .ToLocalChecked();
-  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
-      env->Global()
-          ->Get(context, v8_str(env->GetIsolate(), "f"))
-          .ToLocalChecked());
-
-  // Set script break point on line 1 (in function f).
-  int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
-
-  // Call f with different ignores on the script break point.
-  break_point_hit_count = 0;
-  ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 1);
-  f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
-  CHECK_EQ(0, break_point_hit_count);
-  f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
-  CHECK_EQ(1, break_point_hit_count);
-
-  ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 5);
-  break_point_hit_count = 0;
-  for (int i = 0; i < 10; i++) {
-    f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
-  }
-  CHECK_EQ(5, break_point_hit_count);
-
-  // Reload the script and get f again checking that the ignore survives.
-  v8::Script::Compile(context, script, &origin)
-      .ToLocalChecked()
-      ->Run(context)
-      .ToLocalChecked();
-  f = v8::Local<v8::Function>::Cast(
-      env->Global()
-          ->Get(context, v8_str(env->GetIsolate(), "f"))
-          .ToLocalChecked());
-
-  break_point_hit_count = 0;
-  for (int i = 0; i < 10; i++) {
-    f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
-  }
-  CHECK_EQ(5, break_point_hit_count);
-
-  v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
-  CheckDebuggerUnloaded(env->GetIsolate());
-}
-
-
 // Test that script break points survive when a script is reloaded.
 TEST(ScriptBreakPointReload) {
   break_point_hit_count = 0;
@@ -4405,7 +4327,6 @@
   CheckDebuggerUnloaded(env->GetIsolate());
 }
 
-
 TEST(DisableDebuggerStatement) {
   DebugLocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -7396,7 +7317,7 @@
         CHECK(argument_name->Equals(context, v8_str(isolate, "count"))
                   .FromJust());
         // Get the value of the first argument in frame i. If the
-        // funtion is optimized the value will be undefined, otherwise
+        // function is optimized the value will be undefined, otherwise
         // the value will be '1 - i'.
         //
         // TODO(3141533): We should be able to get the real value for
@@ -8073,3 +7994,81 @@
   v8::Debug::SetDebugEventListener(env->GetIsolate(), NoInterruptsOnDebugEvent);
   CompileRun("void(0);");
 }
+
+class TestBreakLocation : public i::BreakLocation {
+ public:
+  using i::BreakLocation::GetIterator;
+  using i::BreakLocation::Iterator;
+};
+
+TEST(BreakLocationIterator) {
+  DebugLocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  v8::HandleScope scope(isolate);
+
+  v8::Local<v8::Value> result = CompileRun(
+      "function f() {\n"
+      "  debugger;   \n"
+      "  f();        \n"
+      "  debugger;   \n"
+      "}             \n"
+      "f");
+  Handle<i::Object> function_obj = v8::Utils::OpenHandle(*result);
+  Handle<i::JSFunction> function = Handle<i::JSFunction>::cast(function_obj);
+  Handle<i::SharedFunctionInfo> shared(function->shared());
+
+  EnableDebugger(isolate);
+  CHECK(i_isolate->debug()->EnsureDebugInfo(shared, function));
+
+  Handle<i::DebugInfo> debug_info(shared->GetDebugInfo());
+  int code_size = debug_info->abstract_code()->Size();
+
+  bool found_return = false;
+  bool found_call = false;
+  bool found_debugger = false;
+
+  // Test public interface.
+  for (int i = 0; i < code_size; i++) {
+    i::BreakLocation location = i::BreakLocation::FromCodeOffset(debug_info, i);
+    if (location.IsCall()) found_call = true;
+    if (location.IsReturn()) found_return = true;
+    if (location.IsDebuggerStatement()) found_debugger = true;
+  }
+  CHECK(found_call);
+  CHECK(found_return);
+  CHECK(found_debugger);
+
+  // Test underlying implementation.
+  TestBreakLocation::Iterator* iterator =
+      TestBreakLocation::GetIterator(debug_info, i::ALL_BREAK_LOCATIONS);
+  CHECK(iterator->GetBreakLocation().IsDebuggerStatement());
+  CHECK_EQ(7, iterator->GetBreakLocation().position());
+  iterator->Next();
+  CHECK(iterator->GetBreakLocation().IsDebugBreakSlot());
+  CHECK_EQ(22, iterator->GetBreakLocation().position());
+  iterator->Next();
+  CHECK(iterator->GetBreakLocation().IsCall());
+  CHECK_EQ(22, iterator->GetBreakLocation().position());
+  iterator->Next();
+  CHECK(iterator->GetBreakLocation().IsDebuggerStatement());
+  CHECK_EQ(37, iterator->GetBreakLocation().position());
+  iterator->Next();
+  CHECK(iterator->GetBreakLocation().IsReturn());
+  CHECK_EQ(50, iterator->GetBreakLocation().position());
+  iterator->Next();
+  CHECK(iterator->Done());
+  delete iterator;
+
+  iterator = TestBreakLocation::GetIterator(debug_info, i::CALLS_AND_RETURNS);
+  CHECK(iterator->GetBreakLocation().IsCall());
+  CHECK_EQ(22, iterator->GetBreakLocation().position());
+  iterator->Next();
+  CHECK(iterator->GetBreakLocation().IsReturn());
+  CHECK_EQ(50, iterator->GetBreakLocation().position());
+  iterator->Next();
+  CHECK(iterator->Done());
+  delete iterator;
+
+  DisableDebugger(isolate);
+}
diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc
index b3b8a03..74144f2 100644
--- a/test/cctest/test-disasm-arm.cc
+++ b/test/cctest/test-disasm-arm.cc
@@ -362,6 +362,7 @@
   SET_UP();
 
   if (CpuFeatures::IsSupported(ARMv7)) {
+    CpuFeatureScope scope(&assm, ARMv7);
     COMPARE(ubfx(r0, r1, 5, 10),
             "e7e902d1       ubfx r0, r1, #5, #10");
     COMPARE(ubfx(r1, r0, 5, 10),
@@ -437,6 +438,9 @@
     COMPARE(uxth(r3, r4, 8), "e6ff3474       uxth r3, r4, ror #8");
 
     COMPARE(uxtah(r3, r4, r5, 24), "e6f43c75       uxtah r3, r4, r5, ror #24");
+
+    COMPARE(rbit(r1, r2), "e6ff1f32       rbit r1, r2");
+    COMPARE(rbit(r10, ip), "e6ffaf3c       rbit r10, ip");
   }
 
   COMPARE(smmla(r0, r1, r2, r3), "e7503211       smmla r0, r1, r2, r3");
@@ -657,18 +661,27 @@
     COMPARE(vmls(s6, s4, s5, cc),
             "3e023a62       vmlscc.f32 s6, s4, s5");
 
-    COMPARE(vcvt_u32_f64(s0, d0),
-            "eebc0bc0       vcvt.u32.f64 s0, d0");
-    COMPARE(vcvt_s32_f64(s0, d0),
-            "eebd0bc0       vcvt.s32.f64 s0, d0");
-    COMPARE(vcvt_f64_u32(d0, s1),
-            "eeb80b60       vcvt.f64.u32 d0, s1");
-    COMPARE(vcvt_f64_s32(d0, s1),
-            "eeb80be0       vcvt.f64.s32 d0, s1");
-    COMPARE(vcvt_f32_s32(s0, s2),
-            "eeb80ac1       vcvt.f32.s32 s0, s2");
-    COMPARE(vcvt_f64_s32(d0, 2),
-            "eeba0bcf       vcvt.f64.s32 d0, d0, #2");
+    COMPARE(vcvt_f32_f64(s31, d15),
+            "eef7fbcf       vcvt.f32.f64 s31, d15");
+    COMPARE(vcvt_f32_s32(s30, s29),
+            "eeb8faee       vcvt.f32.s32 s30, s29");
+    COMPARE(vcvt_f64_f32(d14, s28),
+            "eeb7eace       vcvt.f64.f32 d14, s28");
+    COMPARE(vcvt_f64_s32(d13, s27),
+            "eeb8dbed       vcvt.f64.s32 d13, s27");
+    COMPARE(vcvt_f64_u32(d12, s26),
+            "eeb8cb4d       vcvt.f64.u32 d12, s26");
+    COMPARE(vcvt_s32_f32(s25, s24),
+            "eefdcacc       vcvt.s32.f32 s25, s24");
+    COMPARE(vcvt_s32_f64(s23, d11),
+            "eefdbbcb       vcvt.s32.f64 s23, d11");
+    COMPARE(vcvt_u32_f32(s22, s21),
+            "eebcbaea       vcvt.u32.f32 s22, s21");
+    COMPARE(vcvt_u32_f64(s20, d10),
+            "eebcabca       vcvt.u32.f64 s20, d10");
+
+    COMPARE(vcvt_f64_s32(d9, 2),
+            "eeba9bcf       vcvt.f64.s32 d9, d9, #2");
 
     if (CpuFeatures::IsSupported(VFP32DREGS)) {
       COMPARE(vmov(d3, d27),
@@ -742,12 +755,27 @@
       COMPARE(vmla(d16, d17, d18),
               "ee410ba2       vmla.f64 d16, d17, d18");
 
-      COMPARE(vcvt_u32_f64(s0, d16),
-              "eebc0be0       vcvt.u32.f64 s0, d16");
-      COMPARE(vcvt_s32_f64(s0, d16),
-              "eebd0be0       vcvt.s32.f64 s0, d16");
-      COMPARE(vcvt_f64_u32(d16, s1),
-              "eef80b60       vcvt.f64.u32 d16, s1");
+      COMPARE(vcvt_f32_f64(s0, d31),
+              "eeb70bef       vcvt.f32.f64 s0, d31");
+      COMPARE(vcvt_f32_s32(s1, s2),
+              "eef80ac1       vcvt.f32.s32 s1, s2");
+      COMPARE(vcvt_f64_f32(d30, s3),
+              "eef7eae1       vcvt.f64.f32 d30, s3");
+      COMPARE(vcvt_f64_s32(d29, s4),
+              "eef8dbc2       vcvt.f64.s32 d29, s4");
+      COMPARE(vcvt_f64_u32(d28, s5),
+              "eef8cb62       vcvt.f64.u32 d28, s5");
+      COMPARE(vcvt_s32_f32(s6, s7),
+              "eebd3ae3       vcvt.s32.f32 s6, s7");
+      COMPARE(vcvt_s32_f64(s8, d27),
+              "eebd4beb       vcvt.s32.f64 s8, d27");
+      COMPARE(vcvt_u32_f32(s9, s10),
+              "eefc4ac5       vcvt.u32.f32 s9, s10");
+      COMPARE(vcvt_u32_f64(s11, d26),
+              "eefc5bea       vcvt.u32.f64 s11, d26");
+
+      COMPARE(vcvt_f64_s32(d25, 2),
+              "eefa9bcf       vcvt.f64.s32 d25, d25, #2");
     }
   }
 
@@ -1003,3 +1031,45 @@
 
   VERIFY_RUN();
 }
+
+
+TEST(Barrier) {
+  SET_UP();
+
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    CpuFeatureScope scope(&assm, ARMv7);
+
+    COMPARE(dmb(OSHLD),
+            "f57ff051       dmb oshld");
+    COMPARE(dmb(OSHST),
+            "f57ff052       dmb oshst");
+    COMPARE(dmb(OSH),
+            "f57ff053       dmb osh");
+    COMPARE(dmb(NSHLD),
+            "f57ff055       dmb nshld");
+    COMPARE(dmb(NSHST),
+            "f57ff056       dmb nshst");
+    COMPARE(dmb(NSH),
+            "f57ff057       dmb nsh");
+    COMPARE(dmb(ISHLD),
+            "f57ff059       dmb ishld");
+    COMPARE(dmb(ISHST),
+            "f57ff05a       dmb ishst");
+    COMPARE(dmb(ISH),
+            "f57ff05b       dmb ish");
+    COMPARE(dmb(LD),
+            "f57ff05d       dmb ld");
+    COMPARE(dmb(ST),
+            "f57ff05e       dmb st");
+    COMPARE(dmb(SY),
+            "f57ff05f       dmb sy");
+
+    COMPARE(dsb(ISH),
+            "f57ff04b       dsb ish");
+
+    COMPARE(isb(ISH),
+            "f57ff06b       isb ish");
+  }
+
+  VERIFY_RUN();
+}
diff --git a/test/cctest/test-extra.js b/test/cctest/test-extra.js
index dfb6c80..b3752d9 100644
--- a/test/cctest/test-extra.js
+++ b/test/cctest/test-extra.js
@@ -12,6 +12,15 @@
     return binding.runtime(3);
   };
 
+  binding.testFunctionToString = function() {
+    function foo() { return 1; }
+    return foo.toString();
+  };
+
+  binding.testStackTrace = function(f) {
+    return f();
+  }
+
   // Exercise all of the extras utils:
   // - v8.createPrivateSymbol
   // - v8.simpleBind, v8.uncurryThis
diff --git a/test/cctest/test-field-type-tracking.cc b/test/cctest/test-field-type-tracking.cc
index 89456bd..cee3600 100644
--- a/test/cctest/test-field-type-tracking.cc
+++ b/test/cctest/test-field-type-tracking.cc
@@ -12,6 +12,7 @@
 #include "src/compilation-cache.h"
 #include "src/execution.h"
 #include "src/factory.h"
+#include "src/field-type.h"
 #include "src/global-handles.h"
 #include "src/ic/stub-cache.h"
 #include "src/macro-assembler.h"
@@ -88,7 +89,7 @@
   PropertyType types_[MAX_PROPERTIES];
   PropertyAttributes attributes_[MAX_PROPERTIES];
   Representation representations_[MAX_PROPERTIES];
-  // HeapType for kField, value for DATA_CONSTANT and getter for
+  // FieldType for kField, value for DATA_CONSTANT and getter for
   // ACCESSOR_CONSTANT.
   Handle<Object> values_[MAX_PROPERTIES];
   // Setter for ACCESSOR_CONSTANT.
@@ -142,25 +143,25 @@
     os << "\n";
   }
 
-  Handle<HeapType> GetFieldType(int index) {
+  Handle<FieldType> GetFieldType(int index) {
     CHECK(index < MAX_PROPERTIES);
     CHECK(types_[index] == DATA || types_[index] == ACCESSOR);
-    return Handle<HeapType>::cast(values_[index]);
+    return Handle<FieldType>::cast(values_[index]);
   }
 
   void SetDataField(int index, PropertyAttributes attrs,
-                    Representation representation, Handle<HeapType> value) {
+                    Representation representation, Handle<FieldType> value) {
     Init(index, DATA, attrs, representation, value);
   }
 
   void SetDataField(int index, Representation representation,
-                    Handle<HeapType> value) {
+                    Handle<FieldType> value) {
     SetDataField(index, attributes_[index], representation, value);
   }
 
   void SetAccessorField(int index, PropertyAttributes attrs) {
     Init(index, ACCESSOR, attrs, Representation::Tagged(),
-         HeapType::Any(isolate_));
+         FieldType::Any(isolate_));
   }
 
   void SetAccessorField(int index) {
@@ -216,7 +217,7 @@
     CHECK(index < number_of_properties_);
     representations_[index] = Representation::Tagged();
     if (types_[index] == DATA || types_[index] == ACCESSOR) {
-      values_[index] = HeapType::Any(isolate_);
+      values_[index] = FieldType::Any(isolate_);
     }
   }
 
@@ -232,8 +233,8 @@
     switch (type) {
       case DATA:
       case ACCESSOR: {
-        HeapType* type = descriptors->GetFieldType(descriptor);
-        return HeapType::cast(expected_value)->Equals(type);
+        FieldType* type = descriptors->GetFieldType(descriptor);
+        return FieldType::cast(expected_value) == type;
       }
 
       case DATA_CONSTANT:
@@ -280,7 +281,7 @@
 
   Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
                            Representation representation,
-                           Handle<HeapType> heap_type) {
+                           Handle<FieldType> heap_type) {
     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     int property_index = number_of_properties_++;
     SetDataField(property_index, attributes, representation, heap_type);
@@ -306,7 +307,7 @@
   Handle<Map> TransitionToDataField(Handle<Map> map,
                                     PropertyAttributes attributes,
                                     Representation representation,
-                                    Handle<HeapType> heap_type,
+                                    Handle<FieldType> heap_type,
                                     Handle<Object> value) {
     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     int property_index = number_of_properties_++;
@@ -332,7 +333,7 @@
   Handle<Map> FollowDataTransition(Handle<Map> map,
                                    PropertyAttributes attributes,
                                    Representation representation,
-                                   Handle<HeapType> heap_type) {
+                                   Handle<FieldType> heap_type) {
     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     int property_index = number_of_properties_++;
     SetDataField(property_index, attributes, representation, heap_type);
@@ -421,8 +422,8 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> none_type = HeapType::None(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> none_type = FieldType::None(isolate);
   Handle<AccessorPair> pair = CreateAccessorPair(true, true);
 
   Expectations expectations(isolate);
@@ -533,12 +534,12 @@
 //
 static void TestGeneralizeRepresentation(
     int detach_property_at_index, int property_index,
-    Representation from_representation, Handle<HeapType> from_type,
-    Representation to_representation, Handle<HeapType> to_type,
-    Representation expected_representation, Handle<HeapType> expected_type,
+    Representation from_representation, Handle<FieldType> from_type,
+    Representation to_representation, Handle<FieldType> to_type,
+    Representation expected_representation, Handle<FieldType> expected_type,
     bool expected_deprecation, bool expected_field_type_dependency) {
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   CHECK(detach_property_at_index >= -1 &&
         detach_property_at_index < kPropCount);
@@ -639,11 +640,10 @@
   CHECK_EQ(*new_map, *updated_map);
 }
 
-
 static void TestGeneralizeRepresentation(
-    Representation from_representation, Handle<HeapType> from_type,
-    Representation to_representation, Handle<HeapType> to_type,
-    Representation expected_representation, Handle<HeapType> expected_type,
+    Representation from_representation, Handle<FieldType> from_type,
+    Representation to_representation, Handle<FieldType> to_type,
+    Representation expected_representation, Handle<FieldType> expected_type,
     bool expected_deprecation, bool expected_field_type_dependency) {
   // Check the cases when the map being reconfigured is a part of the
   // transition tree.
@@ -670,19 +670,18 @@
 
     // Check that reconfiguration to the very same field works correctly.
     Representation representation = from_representation;
-    Handle<HeapType> type = from_type;
+    Handle<FieldType> type = from_type;
     TestGeneralizeRepresentation(-1, 2, representation, type, representation,
                                  type, representation, type, false, false);
   }
 }
 
-
 static void TestGeneralizeRepresentation(Representation from_representation,
-                                         Handle<HeapType> from_type,
+                                         Handle<FieldType> from_type,
                                          Representation to_representation,
-                                         Handle<HeapType> to_type,
+                                         Handle<FieldType> to_type,
                                          Representation expected_representation,
-                                         Handle<HeapType> expected_type) {
+                                         Handle<FieldType> expected_type) {
   const bool expected_deprecation = true;
   const bool expected_field_type_dependency = false;
 
@@ -692,11 +691,10 @@
       expected_field_type_dependency);
 }
 
-
 static void TestGeneralizeRepresentationTrivial(
-    Representation from_representation, Handle<HeapType> from_type,
-    Representation to_representation, Handle<HeapType> to_type,
-    Representation expected_representation, Handle<HeapType> expected_type,
+    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) {
   const bool expected_deprecation = false;
 
@@ -711,7 +709,7 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   TestGeneralizeRepresentation(Representation::Smi(), any_type,
                                Representation::Double(), any_type,
@@ -723,9 +721,9 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
   TestGeneralizeRepresentation(Representation::Smi(), any_type,
                                Representation::HeapObject(), value_type,
@@ -737,9 +735,9 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
   TestGeneralizeRepresentation(Representation::Double(), any_type,
                                Representation::HeapObject(), value_type,
@@ -751,9 +749,9 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
   TestGeneralizeRepresentation(Representation::HeapObject(), value_type,
                                Representation::Smi(), any_type,
@@ -765,29 +763,23 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
-  const int kMaxClassesPerFieldType = 1;
-  Handle<HeapType> current_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> current_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
-  for (int i = 0; i < kMaxClassesPerFieldType; i++) {
-    Handle<HeapType> new_type =
-        HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> new_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
-    Handle<HeapType> expected_type =
-        (i < kMaxClassesPerFieldType - 1)
-            ? HeapType::Union(current_type, new_type, isolate)
-            : any_type;
+  Handle<FieldType> expected_type = any_type;
 
     TestGeneralizeRepresentationTrivial(
         Representation::HeapObject(), current_type,
         Representation::HeapObject(), new_type, Representation::HeapObject(),
         expected_type);
     current_type = expected_type;
-  }
 
-  Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
+    new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
 
   TestGeneralizeRepresentationTrivial(
       Representation::HeapObject(), any_type, Representation::HeapObject(),
@@ -799,8 +791,8 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> none_type = HeapType::None(isolate);
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> none_type = FieldType::None(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   // None -> Smi representation change is trivial.
   TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
@@ -813,8 +805,8 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> none_type = HeapType::None(isolate);
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> none_type = FieldType::None(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   // None -> Double representation change is NOT trivial.
   TestGeneralizeRepresentation(Representation::None(), none_type,
@@ -827,9 +819,9 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> none_type = HeapType::None(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> none_type = FieldType::None(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
   // None -> HeapObject representation change is trivial.
   TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
@@ -842,8 +834,8 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> none_type = HeapType::None(isolate);
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> none_type = FieldType::None(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   // None -> HeapObject representation change is trivial.
   TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
@@ -861,7 +853,7 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
   Handle<AccessorPair> pair = CreateAccessorPair(true, true);
 
   const int kAccessorProp = kPropCount / 2;
@@ -932,9 +924,9 @@
 // where "p2A" and "p2B" differ only in the attributes.
 //
 static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
-    Representation from_representation, Handle<HeapType> from_type,
-    Representation to_representation, Handle<HeapType> to_type,
-    Representation expected_representation, Handle<HeapType> expected_type) {
+    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);
@@ -1016,9 +1008,9 @@
 // where "p2A" and "p2B" differ only in the attributes.
 //
 static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
-    Representation from_representation, Handle<HeapType> from_type,
-    Representation to_representation, Handle<HeapType> to_type,
-    Representation expected_representation, Handle<HeapType> expected_type,
+    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();
 
@@ -1096,7 +1088,7 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
       Representation::Smi(), any_type, Representation::Double(), any_type,
@@ -1108,9 +1100,9 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
   TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
       Representation::Smi(), any_type, Representation::HeapObject(), value_type,
@@ -1122,9 +1114,9 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
   TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
       Representation::Double(), any_type, Representation::HeapObject(),
@@ -1136,29 +1128,22 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
-  const int kMaxClassesPerFieldType = 1;
-  Handle<HeapType> current_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> current_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
-  for (int i = 0; i < kMaxClassesPerFieldType; i++) {
-    Handle<HeapType> new_type =
-        HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> new_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
-    Handle<HeapType> expected_type =
-        (i < kMaxClassesPerFieldType - 1)
-            ? HeapType::Union(current_type, new_type, isolate)
-            : any_type;
+  Handle<FieldType> expected_type = any_type;
 
-    TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
-        Representation::HeapObject(), current_type,
-        Representation::HeapObject(), new_type, Representation::HeapObject(),
-        expected_type);
-    current_type = expected_type;
-  }
+  TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
+      Representation::HeapObject(), current_type, Representation::HeapObject(),
+      new_type, Representation::HeapObject(), expected_type);
+  current_type = expected_type;
 
-  Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
+  new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
 
   TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
       Representation::HeapObject(), any_type, Representation::HeapObject(),
@@ -1170,9 +1155,9 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
   TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
       Representation::HeapObject(), value_type, Representation::Smi(), any_type,
@@ -1268,7 +1253,7 @@
 static void TestReconfigureProperty_CustomPropertyAfterTargetMap(
     TestConfig& config, Checker& checker) {
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   const int kCustomPropIndex = kPropCount - 2;
   Expectations expectations(isolate);
@@ -1391,8 +1376,8 @@
 
     void UpdateExpectations(int property_index, Expectations& expectations) {
       Isolate* isolate = CcTest::i_isolate();
-      Handle<HeapType> function_type =
-          HeapType::Class(isolate->sloppy_function_map(), isolate);
+      Handle<FieldType> function_type =
+          FieldType::Class(isolate->sloppy_function_map(), isolate);
       expectations.SetDataField(property_index, Representation::HeapObject(),
                                 function_type);
     }
@@ -1523,7 +1508,7 @@
         return expectations.AddAccessorConstant(map, NONE, pair_);
       } else {
         Isolate* isolate = CcTest::i_isolate();
-        Handle<HeapType> any_type = HeapType::Any(isolate);
+        Handle<FieldType> any_type = FieldType::Any(isolate);
         return expectations.AddDataField(map, NONE, Representation::Smi(),
                                          any_type);
       }
@@ -1547,7 +1532,7 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   Expectations expectations(isolate);
 
@@ -1638,9 +1623,9 @@
 template <typename TestConfig>
 static void TestGeneralizeRepresentationWithSpecialTransition(
     TestConfig& config, Representation from_representation,
-    Handle<HeapType> from_type, Representation to_representation,
-    Handle<HeapType> to_type, Representation expected_representation,
-    Handle<HeapType> expected_type) {
+    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);
@@ -1730,9 +1715,9 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), 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) {
@@ -1754,14 +1739,14 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), 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<HeapType> any_type = HeapType::Any(isolate);
+      Handle<FieldType> any_type = FieldType::Any(isolate);
 
       // Add one more transition to |map| in order to prevent descriptors
       // ownership.
@@ -1789,9 +1774,9 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), 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) {
@@ -1812,14 +1797,14 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), 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<HeapType> any_type = HeapType::Any(isolate);
+      Handle<FieldType> any_type = FieldType::Any(isolate);
 
       // Add one more transition to |map| in order to prevent descriptors
       // ownership.
@@ -1847,9 +1832,9 @@
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
 
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
   struct TestConfig {
     Handle<JSObject> prototype_;
@@ -1881,9 +1866,9 @@
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
 
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<HeapType> value_type =
-      HeapType::Class(Map::Create(isolate, 0), isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
 
   struct TestConfig {
     Handle<JSObject> prototype_;
@@ -1896,7 +1881,7 @@
 
     Handle<Map> Transition(Handle<Map> map) {
       Isolate* isolate = CcTest::i_isolate();
-      Handle<HeapType> any_type = HeapType::Any(isolate);
+      Handle<FieldType> any_type = FieldType::Any(isolate);
 
       // Add one more transition to |map| in order to prevent descriptors
       // ownership.
@@ -1928,11 +1913,11 @@
 struct TransitionToDataFieldOperator {
   Representation representation_;
   PropertyAttributes attributes_;
-  Handle<HeapType> heap_type_;
+  Handle<FieldType> heap_type_;
   Handle<Object> value_;
 
   TransitionToDataFieldOperator(Representation representation,
-                                Handle<HeapType> heap_type,
+                                Handle<FieldType> heap_type,
                                 Handle<Object> value,
                                 PropertyAttributes attributes = NONE)
       : representation_(representation),
@@ -1979,11 +1964,11 @@
   int descriptor_;
   Representation representation_;
   PropertyAttributes attributes_;
-  Handle<HeapType> heap_type_;
+  Handle<FieldType> heap_type_;
 
   ReconfigureAsDataPropertyOperator(int descriptor,
                                     Representation representation,
-                                    Handle<HeapType> heap_type,
+                                    Handle<FieldType> heap_type,
                                     PropertyAttributes attributes = NONE)
       : descriptor_(descriptor),
         representation_(representation),
@@ -2019,10 +2004,10 @@
   int descriptor_;
   Representation representation_;
   PropertyAttributes attributes_;
-  Handle<HeapType> heap_type_;
+  Handle<FieldType> heap_type_;
 
   FieldGeneralizationChecker(int descriptor, Representation representation,
-                             Handle<HeapType> heap_type,
+                             Handle<FieldType> heap_type,
                              PropertyAttributes attributes = NONE)
       : descriptor_(descriptor),
         representation_(representation),
@@ -2085,7 +2070,7 @@
 static void TestTransitionTo(TransitionOp1& transition_op1,
                              TransitionOp2& transition_op2, Checker& checker) {
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   Expectations expectations(isolate);
 
@@ -2113,7 +2098,7 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   Handle<Object> value1 = handle(Smi::FromInt(0), isolate);
   TransitionToDataFieldOperator transition_op1(Representation::Smi(), any_type,
@@ -2148,8 +2133,8 @@
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
   Factory* factory = isolate->factory();
-  Handle<HeapType> function_type =
-      HeapType::Class(isolate->sloppy_function_map(), isolate);
+  Handle<FieldType> function_type =
+      FieldType::Class(isolate->sloppy_function_map(), isolate);
 
   Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
   TransitionToDataConstantOperator transition_op1(js_func1);
@@ -2168,7 +2153,7 @@
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
   Factory* factory = isolate->factory();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
   TransitionToDataConstantOperator transition_op1(js_func1);
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index a2fd09e..2632593 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -2071,7 +2071,7 @@
   const v8::HeapGraphNode* length_accessor =
       GetProperty(descriptors, v8::HeapGraphEdge::kInternal, "4");
   CHECK(length_accessor);
-  CHECK_EQ(0, strcmp("system / ExecutableAccessorInfo",
+  CHECK_EQ(0, strcmp("system / AccessorInfo",
                      *v8::String::Utf8Value(length_accessor->GetName())));
   const v8::HeapGraphNode* name =
       GetProperty(length_accessor, v8::HeapGraphEdge::kInternal, "name");
@@ -2852,3 +2852,186 @@
   CHECK_EQ(0u, map.size());
   CHECK_EQ(0u, map.GetTraceNodeId(ToAddress(0x400)));
 }
+
+
+static const v8::AllocationProfile::Node* FindAllocationProfileNode(
+    v8::AllocationProfile& profile, const Vector<const char*>& names) {
+  v8::AllocationProfile::Node* node = profile.GetRootNode();
+  for (int i = 0; node != nullptr && i < names.length(); ++i) {
+    const char* name = names[i];
+    auto children = node->children;
+    node = nullptr;
+    for (v8::AllocationProfile::Node* child : children) {
+      v8::String::Utf8Value child_name(child->name);
+      if (strcmp(*child_name, name) == 0) {
+        node = child;
+        break;
+      }
+    }
+  }
+  return node;
+}
+
+
+TEST(SamplingHeapProfiler) {
+  v8::HandleScope scope(v8::Isolate::GetCurrent());
+  LocalContext env;
+  v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+  // Turn off always_opt. Inlining can cause stack traces to be shorter than
+  // what we expect in this test.
+  v8::internal::FLAG_always_opt = false;
+
+  // Suppress randomness to avoid flakiness in tests.
+  v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true;
+
+  const char* script_source =
+      "var A = [];\n"
+      "function bar(size) { return new Array(size); }\n"
+      "var foo = function() {\n"
+      "  for (var i = 0; i < 1024; ++i) {\n"
+      "    A[i] = bar(1024);\n"
+      "  }\n"
+      "}\n"
+      "foo();";
+
+  // Sample should be empty if requested before sampling has started.
+  {
+    v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile();
+    CHECK(profile == nullptr);
+  }
+
+  int count_1024 = 0;
+  {
+    heap_profiler->StartSamplingHeapProfiler(1024);
+    CompileRun(script_source);
+
+    v8::base::SmartPointer<v8::AllocationProfile> profile(
+        heap_profiler->GetAllocationProfile());
+    CHECK(!profile.is_empty());
+
+    const char* names[] = {"", "foo", "bar"};
+    auto node_bar = FindAllocationProfileNode(
+        *profile, Vector<const char*>(names, arraysize(names)));
+    CHECK(node_bar);
+
+    // Count the number of allocations we sampled from bar.
+    for (auto allocation : node_bar->allocations) {
+      count_1024 += allocation.count;
+    }
+
+    heap_profiler->StopSamplingHeapProfiler();
+  }
+
+  // Samples should get cleared once sampling is stopped.
+  {
+    v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile();
+    CHECK(profile == nullptr);
+  }
+
+  // Sampling at a higher rate should give us similar numbers of objects.
+  {
+    heap_profiler->StartSamplingHeapProfiler(128);
+    CompileRun(script_source);
+
+    v8::base::SmartPointer<v8::AllocationProfile> profile(
+        heap_profiler->GetAllocationProfile());
+    CHECK(!profile.is_empty());
+
+    const char* names[] = {"", "foo", "bar"};
+    auto node_bar = FindAllocationProfileNode(
+        *profile, Vector<const char*>(names, arraysize(names)));
+    CHECK(node_bar);
+
+    // Count the number of allocations we sampled from bar.
+    int count_128 = 0;
+    for (auto allocation : node_bar->allocations) {
+      count_128 += allocation.count;
+    }
+
+    // We should have similar unsampled counts of allocations. Though
+    // we will sample different numbers of objects at different rates,
+    // the unsampling process should produce similar final estimates
+    // at the true number of allocations. However, the process to
+    // determine these unsampled counts is probabilisitic so we need to
+    // account for error.
+    double max_count = std::max(count_128, count_1024);
+    double min_count = std::min(count_128, count_1024);
+    double percent_difference = (max_count - min_count) / min_count;
+    CHECK_LT(percent_difference, 0.15);
+
+    heap_profiler->StopSamplingHeapProfiler();
+  }
+
+  // A more complicated test cases with deeper call graph and dynamically
+  // generated function names.
+  {
+    heap_profiler->StartSamplingHeapProfiler(64);
+    CompileRun(record_trace_tree_source);
+
+    v8::base::SmartPointer<v8::AllocationProfile> profile(
+        heap_profiler->GetAllocationProfile());
+    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)));
+    CHECK(node1);
+
+    const char* names2[] = {"", "generateFunctions"};
+    auto node2 = FindAllocationProfileNode(
+        *profile, Vector<const char*>(names2, arraysize(names2)));
+    CHECK(node2);
+
+    heap_profiler->StopSamplingHeapProfiler();
+  }
+}
+
+
+TEST(SamplingHeapProfilerApiAllocation) {
+  v8::HandleScope scope(v8::Isolate::GetCurrent());
+  LocalContext env;
+  v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+  // Suppress randomness to avoid flakiness in tests.
+  v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true;
+
+  heap_profiler->StartSamplingHeapProfiler(256);
+
+  for (int i = 0; i < 8 * 1024; ++i) v8::Object::New(env->GetIsolate());
+
+  v8::base::SmartPointer<v8::AllocationProfile> profile(
+      heap_profiler->GetAllocationProfile());
+  CHECK(!profile.is_empty());
+  const char* names[] = {"(V8 API)"};
+  auto node = FindAllocationProfileNode(
+      *profile, Vector<const char*>(names, arraysize(names)));
+  CHECK(node);
+
+  heap_profiler->StopSamplingHeapProfiler();
+}
+
+TEST(SamplingHeapProfilerLeftTrimming) {
+  v8::HandleScope scope(v8::Isolate::GetCurrent());
+  LocalContext env;
+  v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+  // Suppress randomness to avoid flakiness in tests.
+  v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true;
+
+  heap_profiler->StartSamplingHeapProfiler(64);
+
+  CompileRun(
+      "for (var j = 0; j < 500; ++j) {\n"
+      "  var a = [];\n"
+      "  for (var i = 0; i < 5; ++i)\n"
+      "      a[i] = i;\n"
+      "  for (var i = 0; i < 3; ++i)\n"
+      "      a.shift();\n"
+      "}\n");
+
+  CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
+  // Should not crash.
+
+  heap_profiler->StopSamplingHeapProfiler();
+}
diff --git a/test/cctest/test-inobject-slack-tracking.cc b/test/cctest/test-inobject-slack-tracking.cc
index 6ce77c9..5cc4e94 100644
--- a/test/cctest/test-inobject-slack-tracking.cc
+++ b/test/cctest/test-inobject-slack-tracking.cc
@@ -61,9 +61,9 @@
   ScriptContextTable::LookupResult lookup_result;
   if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
     Handle<Object> result =
-        FixedArray::get(ScriptContextTable::GetContext(
+        FixedArray::get(*ScriptContextTable::GetContext(
                             script_contexts, lookup_result.context_index),
-                        lookup_result.slot_index);
+                        lookup_result.slot_index, isolate);
     return Handle<T>::cast(result);
   }
   return Handle<T>();
diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index 7254ee0..21dafda 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -83,6 +83,11 @@
   frame_iterator.Advance();
   CHECK(frame_iterator.frame()->is_construct());
   frame_iterator.Advance();
+  if (i::FLAG_ignition) {
+    // Skip over bytecode handler frame.
+    CHECK(frame_iterator.frame()->type() == i::StackFrame::STUB);
+    frame_iterator.Advance();
+  }
   i::StackFrame* calling_frame = frame_iterator.frame();
   CHECK(calling_frame->is_java_script());
 
@@ -175,7 +180,8 @@
   //           TickSample::Trace
 
   CHECK(sample.has_external_callback);
-  CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::Trace), sample.external_callback);
+  CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::Trace),
+           sample.external_callback_entry);
 
   // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
   unsigned base = 0;
@@ -229,7 +235,8 @@
   //
 
   CHECK(sample.has_external_callback);
-  CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::JSTrace), sample.external_callback);
+  CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::JSTrace),
+           sample.external_callback_entry);
 
   // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
   unsigned base = 0;
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index adbd1a5..8077f65 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -370,10 +370,14 @@
         i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
     CHECK(exists);
 
+    Address ObjMethod1_entry = reinterpret_cast<Address>(ObjMethod1);
+#if USES_FUNCTION_DESCRIPTORS
+    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));
+                reinterpret_cast<intptr_t>(ObjMethod1_entry));
 
     CHECK(StrNStr(log.start(), ref_data.start(), log.length()));
     log.Dispose();
@@ -419,22 +423,34 @@
         i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
     CHECK(exists);
 
+    Address Prop1Getter_entry = reinterpret_cast<Address>(Prop1Getter);
+#if USES_FUNCTION_DESCRIPTORS
+    Prop1Getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(Prop1Getter_entry);
+#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));
+                reinterpret_cast<intptr_t>(Prop1Getter_entry));
     CHECK(StrNStr(log.start(), prop1_getter_record.start(), log.length()));
 
+    Address Prop1Setter_entry = reinterpret_cast<Address>(Prop1Setter);
+#if USES_FUNCTION_DESCRIPTORS
+    Prop1Setter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(Prop1Setter_entry);
+#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));
+                reinterpret_cast<intptr_t>(Prop1Setter_entry));
     CHECK(StrNStr(log.start(), prop1_setter_record.start(), log.length()));
 
+    Address Prop2Getter_entry = reinterpret_cast<Address>(Prop2Getter);
+#if USES_FUNCTION_DESCRIPTORS
+    Prop2Getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(Prop2Getter_entry);
+#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));
+                reinterpret_cast<intptr_t>(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 696ca01..77dc859 100644
--- a/test/cctest/test-macro-assembler-mips.cc
+++ b/test/cctest/test-macro-assembler-mips.cc
@@ -185,7 +185,7 @@
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
   HandleScope scope(isolate);
-  MacroAssembler assembler(isolate, NULL, 0,
+  MacroAssembler assembler(isolate, nullptr, 0,
                            v8::internal::CodeObjectRequired::kYes);
   MacroAssembler* masm = &assembler;
 
@@ -193,11 +193,9 @@
   int values[kNumCases];
   isolate->random_number_generator()->NextBytes(values, sizeof(values));
   Label labels[kNumCases];
-  Label near_start, end;
+  Label near_start, end, done;
 
-  __ addiu(sp, sp, -4);
-  __ sw(ra, MemOperand(sp));
-
+  __ Push(ra);
   __ mov(v0, zero_reg);
 
   __ Branch(&end);
@@ -209,35 +207,17 @@
     __ addiu(v0, v0, 1);
   }
 
-  Label done;
-  {
-    __ BlockTrampolinePoolFor(kNumCases + 6);
-    PredictableCodeSizeScope predictable(
-        masm, (kNumCases + 6) * Assembler::kInstrSize);
-    Label here;
-
-    __ bal(&here);
-    __ sll(at, a0, 2);  // In delay slot.
-    __ bind(&here);
-    __ addu(at, at, ra);
-    __ lw(at, MemOperand(at, 4 * Assembler::kInstrSize));
-    __ jr(at);
-    __ nop();  // Branch delay slot nop.
-    for (int i = 0; i < kNumCases; ++i) {
-      __ dd(&labels[i]);
-    }
-  }
+  __ GenerateSwitchTable(a0, kNumCases,
+                         [&labels](size_t i) { return labels + i; });
 
   for (int i = 0; i < kNumCases; ++i) {
     __ bind(&labels[i]);
-    __ lui(v0, (values[i] >> 16) & 0xffff);
-    __ ori(v0, v0, values[i] & 0xffff);
+    __ li(v0, values[i]);
     __ Branch(&done);
   }
 
   __ bind(&done);
-  __ lw(ra, MemOperand(sp));
-  __ addiu(sp, sp, 4);
+  __ Pop(ra);
   __ jr(ra);
   __ nop();
 
@@ -279,23 +259,21 @@
   Label labels[kNumCases];
   Label done;
 
-  __ addiu(sp, sp, -4);
-  __ sw(ra, MemOperand(sp));
+  __ Push(ra);
 
   {
-    __ BlockTrampolinePoolFor(kNumCases * 2 + 7 + 1);
+    __ BlockTrampolinePoolFor(kNumCases + 6 + 1);
     PredictableCodeSizeScope predictable(
-        masm, kNumCases * kPointerSize + ((7 + 1) * Assembler::kInstrSize));
-    Label here;
+        masm, kNumCases * kPointerSize + ((6 + 1) * Assembler::kInstrSize));
 
-    __ bal(&here);
-    __ sll(at, a0, 2);  // In delay slot.
-    __ bind(&here);
-    __ addu(at, at, ra);
-    __ lw(at, MemOperand(at, 6 * Assembler::kInstrSize));
+    __ addiupc(at, 6 + 1);
+    __ lsa(at, at, a0, 2);
+    __ lw(at, MemOperand(at));
     __ jalr(at);
     __ nop();  // Branch delay slot nop.
     __ bc(&done);
+    // A nop instruction must be generated by the forbidden slot guard
+    // (Assembler::dd(Label*)).
     for (int i = 0; i < kNumCases; ++i) {
       __ dd(&labels[i]);
     }
@@ -303,15 +281,13 @@
 
   for (int i = 0; i < kNumCases; ++i) {
     __ bind(&labels[i]);
-    __ lui(v0, (values[i] >> 16) & 0xffff);
-    __ ori(v0, v0, values[i] & 0xffff);
+    __ li(v0, values[i]);
     __ jr(ra);
     __ nop();
   }
 
   __ bind(&done);
-  __ lw(ra, MemOperand(sp));
-  __ addiu(sp, sp, 4);
+  __ Pop(ra);
   __ jr(ra);
   __ nop();
 
diff --git a/test/cctest/test-macro-assembler-mips64.cc b/test/cctest/test-macro-assembler-mips64.cc
index 684b554..e74703b 100644
--- a/test/cctest/test-macro-assembler-mips64.cc
+++ b/test/cctest/test-macro-assembler-mips64.cc
@@ -228,7 +228,7 @@
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
   HandleScope scope(isolate);
-  MacroAssembler assembler(isolate, NULL, 0,
+  MacroAssembler assembler(isolate, nullptr, 0,
                            v8::internal::CodeObjectRequired::kYes);
   MacroAssembler* masm = &assembler;
 
@@ -236,11 +236,9 @@
   int values[kNumCases];
   isolate->random_number_generator()->NextBytes(values, sizeof(values));
   Label labels[kNumCases];
-  Label near_start, end;
+  Label near_start, end, done;
 
-  __ daddiu(sp, sp, -8);
-  __ sd(ra, MemOperand(sp));
-
+  __ Push(ra);
   __ mov(v0, zero_reg);
 
   __ Branch(&end);
@@ -252,36 +250,17 @@
     __ addiu(v0, v0, 1);
   }
 
-  __ Align(8);
-  Label done;
-  {
-    __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
-    PredictableCodeSizeScope predictable(
-        masm, (kNumCases * 2 + 6) * Assembler::kInstrSize);
-    Label here;
-
-    __ bal(&here);
-    __ dsll(at, a0, 3);  // In delay slot.
-    __ bind(&here);
-    __ daddu(at, at, ra);
-    __ ld(at, MemOperand(at, 4 * Assembler::kInstrSize));
-    __ jr(at);
-    __ nop();  // Branch delay slot nop.
-    for (int i = 0; i < kNumCases; ++i) {
-      __ dd(&labels[i]);
-    }
-  }
+  __ GenerateSwitchTable(a0, kNumCases,
+                         [&labels](size_t i) { return labels + i; });
 
   for (int i = 0; i < kNumCases; ++i) {
     __ bind(&labels[i]);
-    __ lui(v0, (values[i] >> 16) & 0xffff);
-    __ ori(v0, v0, values[i] & 0xffff);
+    __ li(v0, values[i]);
     __ Branch(&done);
   }
 
   __ bind(&done);
-  __ ld(ra, MemOperand(sp));
-  __ daddiu(sp, sp, 8);
+  __ Pop(ra);
   __ jr(ra);
   __ nop();
 
@@ -323,21 +302,22 @@
   Label labels[kNumCases];
   Label done;
 
-  __ daddiu(sp, sp, -8);
-  __ sd(ra, MemOperand(sp));
+  __ Push(ra);
 
-  __ Align(8);
+  // Opposite of Align(8) as we have unaligned number of instructions in the
+  // following block before the first dd().
+  if ((masm->pc_offset() & 7) == 0) {
+    __ nop();
+  }
+
   {
-    __ BlockTrampolinePoolFor(kNumCases * 2 + 7 + 1);
+    __ BlockTrampolinePoolFor(kNumCases * 2 + 6 + 1);
     PredictableCodeSizeScope predictable(
-        masm, kNumCases * kPointerSize + ((7 + 1) * Assembler::kInstrSize));
-    Label here;
+        masm, kNumCases * kPointerSize + ((6 + 1) * Assembler::kInstrSize));
 
-    __ bal(&here);
-    __ dsll(at, a0, 3);  // In delay slot.
-    __ bind(&here);
-    __ daddu(at, at, ra);
-    __ ld(at, MemOperand(at, 6 * Assembler::kInstrSize));
+    __ addiupc(at, 6 + 1);
+    __ dlsa(at, at, a0, 3);
+    __ ld(at, MemOperand(at));
     __ jalr(at);
     __ nop();  // Branch delay slot nop.
     __ bc(&done);
@@ -351,15 +331,13 @@
 
   for (int i = 0; i < kNumCases; ++i) {
     __ bind(&labels[i]);
-    __ lui(v0, (values[i] >> 16) & 0xffff);
-    __ ori(v0, v0, values[i] & 0xffff);
+    __ li(v0, values[i]);
     __ jr(ra);
     __ nop();
   }
 
   __ bind(&done);
-  __ ld(ra, MemOperand(sp));
-  __ daddiu(sp, sp, 8);
+  __ Pop(ra);
   __ jr(ra);
   __ nop();
 
diff --git a/test/cctest/test-object-observe.cc b/test/cctest/test-object-observe.cc
index f0af22e..5164b87 100644
--- a/test/cctest/test-object-observe.cc
+++ b/test/cctest/test-object-observe.cc
@@ -1026,9 +1026,9 @@
   CHECK_EQ(1, use_counts[v8::Isolate::kObjectObserve]);
 }
 
-
 static bool NamedAccessCheckAlwaysAllow(Local<v8::Context> accessing_context,
-                                        Local<v8::Object> accessed_object) {
+                                        Local<v8::Object> accessed_object,
+                                        Local<v8::Value> data) {
   return true;
 }
 
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 5249314..b04fb94 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -1500,7 +1500,6 @@
   return i::MessageTemplate::FormatMessage(isolate, message, arg_object);
 }
 
-
 enum ParserFlag {
   kAllowLazy,
   kAllowNatives,
@@ -1511,10 +1510,10 @@
   kAllowHarmonyDestructuringAssignment,
   kAllowHarmonyNewTarget,
   kAllowStrongMode,
-  kNoLegacyConst
+  kNoLegacyConst,
+  kAllowHarmonyFunctionSent
 };
 
-
 enum ParserSyncTestResult {
   kSuccessOrError,
   kSuccess,
@@ -1536,6 +1535,8 @@
       flags.Contains(kAllowHarmonyDestructuringAssignment));
   parser->set_allow_strong_mode(flags.Contains(kAllowStrongMode));
   parser->set_allow_legacy_const(!flags.Contains(kNoLegacyConst));
+  parser->set_allow_harmony_function_sent(
+      flags.Contains(kAllowHarmonyFunctionSent));
 }
 
 
@@ -3712,6 +3713,8 @@
 TEST(ErrorsArrowFunctions) {
   // Tests that parser and preparser generate the same kind of errors
   // on invalid arrow function syntax.
+
+  // clang-format off
   const char* context_data[][2] = {
     {"", ";"},
     {"v = ", ";"},
@@ -3812,8 +3815,14 @@
     "(c, a.b) => {}",
     "(a['b'], c) => {}",
     "(c, a['b']) => {}",
+
+    // crbug.com/582626
+    "(...rest - a) => b",
+    "(a, ...b - 10) => b",
+
     NULL
   };
+  // clang-format on
 
   // The test is quite slow, so run it with a reduced set of flags.
   static const ParserFlag flags[] = {kAllowLazy};
@@ -4445,6 +4454,7 @@
 
 
 TEST(ClassBodyNoErrors) {
+  // clang-format off
   // Tests that parser and preparser accept valid class syntax.
   const char* context_data[][2] = {{"(class {", "});"},
                                    {"(class extends Base {", "});"},
@@ -4467,6 +4477,8 @@
     "; *g() {}",
     "*g() {}; *h(x) {}",
     "static() {}",
+    "get static() {}",
+    "set static(v) {}",
     "static m() {}",
     "static get x() {}",
     "static set x(v) {}",
@@ -4476,10 +4488,23 @@
     "static get static() {}",
     "static set static(v) {}",
     "*static() {}",
+    "static *static() {}",
     "*get() {}",
     "*set() {}",
     "static *g() {}",
+
+    // Escaped 'static' should be allowed anywhere
+    // static-as-PropertyName is.
+    "st\\u0061tic() {}",
+    "get st\\u0061tic() {}",
+    "set st\\u0061tic(v) {}",
+    "static st\\u0061tic() {}",
+    "static get st\\u0061tic() {}",
+    "static set st\\u0061tic(v) {}",
+    "*st\\u0061tic() {}",
+    "static *st\\u0061tic() {}",
     NULL};
+  // clang-format on
 
   static const ParserFlag always_flags[] = {
     kAllowHarmonySloppy
@@ -4928,6 +4953,23 @@
 }
 
 
+TEST(StatementParsingInForIn) {
+  const char* context_data[][2] = {{"", ""},
+                                   {"'use strict';", ""},
+                                   {"function foo(){ 'use strict';", "}"},
+                                   {NULL, NULL}};
+
+  const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
+                        "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
+                        NULL};
+
+  static const ParserFlag always_flags[] = {
+      kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
+  RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
+                    arraysize(always_flags));
+}
+
+
 TEST(ConstParsingInForInError) {
   const char* context_data[][2] = {{"'use strict';", ""},
                                    {"function foo(){ 'use strict';", "}"},
@@ -5101,6 +5143,76 @@
 }
 
 
+TEST(ForOfInOperator) {
+  const char* context_data[][2] = {{"", ""},
+                                   {"'use strict';", ""},
+                                   {"function foo(){ 'use strict';", "}"},
+                                   {NULL, NULL}};
+
+  const char* data[] = {
+      "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, kNoLegacyConst};
+  RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
+                    arraysize(always_flags));
+}
+
+
+TEST(ForOfYieldIdentifier) {
+  const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
+
+  const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
+                        "for(let x of yield) {}", "for(const x of yield) {}",
+                        NULL};
+
+  static const ParserFlag always_flags[] = {
+      kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
+  RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
+                    arraysize(always_flags));
+}
+
+
+TEST(ForOfYieldExpression) {
+  const char* context_data[][2] = {{"", ""},
+                                   {"'use strict';", ""},
+                                   {"function foo(){ 'use strict';", "}"},
+                                   {NULL, NULL}};
+
+  const char* data[] = {"function* g() { for(x of yield) {} }",
+                        "function* g() { for(var x of yield) {} }",
+                        "function* g() { for(let x of yield) {} }",
+                        "function* g() { for(const x of yield) {} }", NULL};
+
+  static const ParserFlag always_flags[] = {
+      kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
+  RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
+                    arraysize(always_flags));
+}
+
+
+TEST(ForOfExpressionError) {
+  const char* context_data[][2] = {{"", ""},
+                                   {"'use strict';", ""},
+                                   {"function foo(){ 'use strict';", "}"},
+                                   {NULL, NULL}};
+
+  const char* data[] = {
+      "for(x of [], []) {}", "for(var x of [], []) {}",
+      "for(let x of [], []) {}", "for(const x of [], []) {}",
+
+      // AssignmentExpression should be validated statically:
+      "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, kNoLegacyConst};
+  RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
+                    arraysize(always_flags));
+}
+
+
 TEST(InvalidUnicodeEscapes) {
   const char* context_data[][2] = {{"", ""},
                                    {"'use strict';", ""},
@@ -5558,6 +5670,7 @@
 TEST(BasicImportExportParsing) {
   i::FLAG_harmony_modules = true;
 
+  // clang-format off
   const char* kSources[] = {
       "export let x = 0;",
       "export var y = 0;",
@@ -5569,7 +5682,11 @@
       "var a, b, c; export { a, b as baz, c };",
       "var d, e; export { d as dreary, e, };",
       "export default function f() {}",
+      "export default function() {}",
+      "export default function*() {}",
       "export default class C {}",
+      "export default class {}"
+      "export default class extends C {}"
       "export default 42",
       "var x; export default x = 7",
       "export { Q } from 'somemodule.js';",
@@ -5596,6 +5713,7 @@
       "import { static as s } from 'm.js';",
       "import { let as l } from 'm.js';",
   };
+  // clang-format on
 
   i::Isolate* isolate = CcTest::i_isolate();
   i::Factory* factory = isolate->factory();
@@ -5652,6 +5770,7 @@
 TEST(ImportExportParsingErrors) {
   i::FLAG_harmony_modules = true;
 
+  // clang-format off
   const char* kErrorSources[] = {
       "export {",
       "var a; export { a",
@@ -5680,6 +5799,10 @@
       "var a, b; export { a as c, b as c };",
       "export default function f(){}; export default class C {};",
       "export default function f(){}; var a; export { a as default };",
+      "export function() {}",
+      "export function*() {}",
+      "export class {}",
+      "export class extends C {}",
 
       "import from;",
       "import from 'm.js';",
@@ -5708,11 +5831,8 @@
       "import * as x, * as y from 'm.js';",
       "import {x}, {y} from 'm.js';",
       "import * as x, {y} from 'm.js';",
-
-      // TODO(ES6): These two forms should be supported
-      "export default function() {};",
-      "export default class {};"
   };
+  // clang-format on
 
   i::Isolate* isolate = CcTest::i_isolate();
   i::Factory* factory = isolate->factory();
@@ -6538,61 +6658,9 @@
 }
 
 
-TEST(StrongModeFreeVariablesNotDeclared) {
-  i::FLAG_strong_mode = true;
-  v8::V8::Initialize();
-  v8::HandleScope scope(CcTest::isolate());
-  v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
-  v8::TryCatch try_catch(CcTest::isolate());
-
-  // Test that referencing unintroduced variables in sloppy mode is ok.
-  const char* script1 =
-      "if (false) {            \n"
-      "  not_there1;           \n"
-      "}                       \n";
-  CompileRun(v8_str(script1));
-  CHECK(!try_catch.HasCaught());
-
-  // But not in strong mode.
-  {
-    const char* script2 =
-        "\"use strong\";         \n"
-        "if (false) {            \n"
-        "  not_there2;           \n"
-        "}                       \n";
-    v8::TryCatch try_catch2(CcTest::isolate());
-    v8_compile(v8_str(script2));
-    CHECK(try_catch2.HasCaught());
-    v8::String::Utf8Value exception(try_catch2.Exception());
-    CHECK_EQ(0,
-             strcmp(
-                 "ReferenceError: In strong mode, using an undeclared global "
-                 "variable 'not_there2' is not allowed",
-                 *exception));
-  }
-
-  // Check that the variable reference is detected inside a strong function too,
-  // even if the script scope is not strong.
-  {
-    const char* script3 =
-        "(function not_lazy() {  \n"
-        "  \"use strong\";       \n"
-        "  if (false) {          \n"
-        "    not_there3;         \n"
-        "  }                     \n"
-        "})();                   \n";
-    v8::TryCatch try_catch2(CcTest::isolate());
-    v8_compile(v8_str(script3));
-    CHECK(try_catch2.HasCaught());
-    v8::String::Utf8Value exception(try_catch2.Exception());
-    CHECK_EQ(0,
-             strcmp(
-                 "ReferenceError: In strong mode, using an undeclared global "
-                 "variable 'not_there3' is not allowed",
-                 *exception));
-  }
-}
-
+static const ParserFlag kAllDestructuringFlags[] = {
+    kAllowHarmonyDestructuring, kAllowHarmonyDestructuringAssignment,
+    kAllowHarmonyDefaultParameters};
 
 TEST(DestructuringPositiveTests) {
   i::FLAG_harmony_destructuring_bind = true;
@@ -6650,6 +6718,8 @@
   static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
                     arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kSuccess, NULL, 0,
+                    kAllDestructuringFlags, arraysize(kAllDestructuringFlags));
 }
 
 
@@ -6727,6 +6797,10 @@
         "[...rest,...rest1]",
         "[a,b,...rest,...rest1]",
         "[a,,..rest,...rest1]",
+        "[x, y, ...z = 1]",
+        "[...z = 1]",
+        "[x, y, ...[z] = [1]]",
+        "[...[z] = [1]]",
         "{ x : 3 }",
         "{ x : 'foo' }",
         "{ x : /foo/ }",
@@ -6739,6 +6813,9 @@
     // clang-format on
     RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
                       arraysize(always_flags));
+    RunParserSyncTest(context_data, data, kError, NULL, 0,
+                      kAllDestructuringFlags,
+                      arraysize(kAllDestructuringFlags));
   }
 
   {  // All modes.
@@ -6759,6 +6836,9 @@
     // clang-format on
     RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
                       arraysize(always_flags));
+    RunParserSyncTest(context_data, data, kError, NULL, 0,
+                      kAllDestructuringFlags,
+                      arraysize(kAllDestructuringFlags));
   }
 
   {  // Strict mode.
@@ -6779,6 +6859,9 @@
     // clang-format on
     RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
                       arraysize(always_flags));
+    RunParserSyncTest(context_data, data, kError, NULL, 0,
+                      kAllDestructuringFlags,
+                      arraysize(kAllDestructuringFlags));
   }
 
   {  // 'yield' in generators.
@@ -6797,6 +6880,9 @@
     // clang-format on
     RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
                       arraysize(always_flags));
+    RunParserSyncTest(context_data, data, kError, NULL, 0,
+                      kAllDestructuringFlags,
+                      arraysize(kAllDestructuringFlags));
   }
 
   { // Declaration-specific errors
@@ -7083,6 +7169,8 @@
     "[...x,]",
     "[x, y, ...z = 1]",
     "[...z = 1]",
+    "[x, y, ...[z] = [1]]",
+    "[...[z] = [1]]",
 
     // v8:4657
     "({ x: x4, x: (x+=1e4) })",
@@ -7333,14 +7421,7 @@
     "x, y=f(yield)",
     "{x=f(yield)}",
     "[x=f(yield)]",
-    NULL
-  };
 
-  // TODO(wingo): These aren't really destructuring assignment patterns; we're
-  // just splitting them for now until the parser gets support for arrow
-  // function arguments that look like destructuring assignments.  When that
-  // happens we should unify destructuring_assignment_data and parameter_data.
-  const char* destructuring_assignment_data[] = {
     "{x}=yield",
     "[x]=yield",
 
@@ -7359,26 +7440,16 @@
 
   RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess,
                     NULL, 0, always_flags, arraysize(always_flags));
-  RunParserSyncTest(sloppy_function_context_data, destructuring_assignment_data,
-                    kSuccess, NULL, 0, always_flags, arraysize(always_flags));
   RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess, NULL,
                     0, always_flags, arraysize(always_flags));
-  RunParserSyncTest(sloppy_arrow_context_data, destructuring_assignment_data,
-                    kSuccess, NULL, 0, always_flags, arraysize(always_flags));
 
   RunParserSyncTest(strict_function_context_data, parameter_data, kError, NULL,
                     0, always_flags, arraysize(always_flags));
-  RunParserSyncTest(strict_function_context_data, destructuring_assignment_data,
-                    kError, NULL, 0, always_flags, arraysize(always_flags));
   RunParserSyncTest(strict_arrow_context_data, parameter_data, kError, NULL, 0,
                     always_flags, arraysize(always_flags));
-  RunParserSyncTest(strict_arrow_context_data, destructuring_assignment_data,
-                    kError, NULL, 0, always_flags, arraysize(always_flags));
 
   RunParserSyncTest(generator_context_data, parameter_data, kError, NULL, 0,
                     always_flags, arraysize(always_flags));
-  RunParserSyncTest(generator_context_data, destructuring_assignment_data,
-                    kError, NULL, 0, always_flags, arraysize(always_flags));
 }
 
 
@@ -7689,6 +7760,13 @@
     "for (const [let] = 1; let < 1; let++) {}",
     "for (const [let] in {}) {}",
     "for (const [let] of []) {}",
+
+    // Sprinkle in the escaped version too.
+    "let l\\u0065t = 1",
+    "const l\\u0065t = 1",
+    "let [l\\u0065t] = 1",
+    "const [l\\u0065t] = 1",
+    "for (let l\\u0065t in {}) {}",
     NULL
   };
   // clang-format on
@@ -7747,6 +7825,7 @@
     "wh\\u0069le (true) { }",
     "w\\u0069th (this.scope) { }",
     "(function*() { y\\u0069eld 1; })()",
+    "(function*() { var y\\u0069eld = 1; })()",
 
     "var \\u0065num = 1;",
     "var { \\u0065num } = {}",
@@ -7784,7 +7863,11 @@
     "do { ; } wh\\u0069le (true) { }",
     "(function*() { return (n++, y\\u0069eld 1); })()",
     "class C { st\\u0061tic bar() {} }",
+    "class C { st\\u0061tic *bar() {} }",
+    "class C { st\\u0061tic get bar() {} }",
+    "class C { st\\u0061tic set bar() {} }",
 
+    // TODO(adamk): These should not be errors in sloppy mode.
     "(y\\u0069eld);",
     "var y\\u0069eld = 1;",
     "var { y\\u0069eld } = {};",
@@ -7810,14 +7893,14 @@
   };
   // clang-format on
 
-  RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0,
+  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, kAllowHarmonyDestructuring};
-  RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0,
+  RunParserSyncTest(sloppy_context_data, let_data, kSuccess, NULL, 0,
                     sloppy_let_flags, arraysize(sloppy_let_flags));
 
   // Non-errors in sloppy mode
@@ -7839,6 +7922,9 @@
                               "(publ\\u0069c);",
                               "var publ\\u0069c = 1;",
                               "var { publ\\u0069c } = {};",
+                              "(st\\u0061tic);",
+                              "var st\\u0061tic = 1;",
+                              "var { st\\u0061tic } = {};",
                               NULL};
   RunParserSyncTest(sloppy_context_data, valid_data, kSuccess, NULL, 0,
                     always_flags, arraysize(always_flags));
@@ -7850,9 +7936,55 @@
 
 
 TEST(MiscSyntaxErrors) {
+  // clang-format off
   const char* context_data[][2] = {
-      {"'use strict'", ""}, {"", ""}, {NULL, NULL}};
-  const char* error_data[] = {"for (();;) {}", NULL};
+    { "'use strict'", "" },
+    { "", "" },
+    { NULL, NULL }
+  };
+  const char* error_data[] = {
+    "for (();;) {}",
+
+    // crbug.com/582626
+    "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
+    NULL
+  };
+  // clang-format on
 
   RunParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0);
 }
+
+TEST(FunctionSentErrors) {
+  // clang-format off
+  const char* context_data[][2] = {
+    { "'use strict'", "" },
+    { "", "" },
+    { NULL, NULL }
+  };
+  const char* error_data[] = {
+    "var x = function.sent",
+    "function* g() { yield function.s\\u0065nt; }",
+    NULL
+  };
+  // clang-format on
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyFunctionSent};
+  RunParserSyncTest(context_data, error_data, kError, always_flags,
+                    arraysize(always_flags));
+}
+
+TEST(NewTargetErrors) {
+  // clang-format off
+  const char* context_data[][2] = {
+    { "'use strict'", "" },
+    { "", "" },
+    { NULL, NULL }
+  };
+  const char* error_data[] = {
+    "var x = new.target",
+    "function f() { return new.t\\u0061rget; }",
+    NULL
+  };
+  // clang-format on
+  RunParserSyncTest(context_data, error_data, kError);
+}
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index 82c0f30..fa7dc15 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -428,11 +428,13 @@
   // (root)#1 -> aaa #2 -> bbb #4 -> ccc #5 - sample2
   //                    -> ccc #6 -> aaa #7 - sample3
   TickSample sample1;
+  sample1.timestamp = v8::base::TimeTicks::HighResolutionNow();
   sample1.pc = ToAddress(0x1600);
   sample1.stack[0] = ToAddress(0x1510);
   sample1.frames_count = 1;
   generator.RecordTickSample(sample1);
   TickSample sample2;
+  sample2.timestamp = v8::base::TimeTicks::HighResolutionNow();
   sample2.pc = ToAddress(0x1925);
   sample2.stack[0] = ToAddress(0x1780);
   sample2.stack[1] = ToAddress(0x10000);  // non-existent.
@@ -440,6 +442,7 @@
   sample2.frames_count = 3;
   generator.RecordTickSample(sample2);
   TickSample sample3;
+  sample3.timestamp = v8::base::TimeTicks::HighResolutionNow();
   sample3.pc = ToAddress(0x1510);
   sample3.stack[0] = ToAddress(0x1910);
   sample3.stack[1] = ToAddress(0x1610);
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index a91058c..22321c3 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -96,7 +96,7 @@
   FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
   RegExpCompileData result;
   return v8::internal::RegExpParser::ParseRegExp(
-      CcTest::i_isolate(), &zone, &reader, false, false, &result);
+      CcTest::i_isolate(), &zone, &reader, JSRegExp::kNone, &result);
 }
 
 
@@ -106,8 +106,10 @@
   Zone zone;
   FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
   RegExpCompileData result;
-  CHECK(v8::internal::RegExpParser::ParseRegExp(
-      CcTest::i_isolate(), &zone, &reader, false, unicode, &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());
   std::ostringstream os;
@@ -125,7 +127,7 @@
   FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
   RegExpCompileData result;
   CHECK(v8::internal::RegExpParser::ParseRegExp(
-      CcTest::i_isolate(), &zone, &reader, false, false, &result));
+      CcTest::i_isolate(), &zone, &reader, JSRegExp::kNone, &result));
   CHECK(result.tree != NULL);
   CHECK(result.error.is_null());
   return result.simple;
@@ -143,7 +145,7 @@
   FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
   RegExpCompileData result;
   CHECK(v8::internal::RegExpParser::ParseRegExp(
-      CcTest::i_isolate(), &zone, &reader, false, false, &result));
+      CcTest::i_isolate(), &zone, &reader, JSRegExp::kNone, &result));
   CHECK(result.tree != NULL);
   CHECK(result.error.is_null());
   int min_match = result.tree->min_match();
@@ -206,8 +208,8 @@
   }
   CheckParseEq("()", "(^ %)");
   CheckParseEq("(?=)", "(-> + %)");
-  CheckParseEq("[]", "^[\\x00-\\uffff]");  // Doesn't compile on windows
-  CheckParseEq("[^]", "[\\x00-\\uffff]");  // \uffff isn't in codepage 1252
+  CheckParseEq("[]", "^[\\x00-\\u{10ffff}]");  // Doesn't compile on windows
+  CheckParseEq("[^]", "[\\x00-\\u{10ffff}]");  // \uffff isn't in codepage 1252
   CheckParseEq("[x]", "[x]");
   CheckParseEq("[xyz]", "[x y z]");
   CheckParseEq("[a-zA-Z0-9]", "[a-z A-Z 0-9]");
@@ -316,6 +318,10 @@
   CheckParseEq("\\u{12345}{3}", "(# 3 3 g '\\ud808\\udf45')", true);
   CheckParseEq("\\u{12345}*", "(# 0 - g '\\ud808\\udf45')", true);
 
+  CheckParseEq("\\ud808\\udf45*", "(# 0 - g '\\ud808\\udf45')", true);
+  CheckParseEq("[\\ud808\\udf45-\\ud809\\udccc]", "[\\u{012345}-\\u{0124cc}]",
+               true);
+
   CHECK_SIMPLE("", false);
   CHECK_SIMPLE("a", true);
   CHECK_SIMPLE("a|b", false);
@@ -454,7 +460,7 @@
   FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
   RegExpCompileData result;
   CHECK(!v8::internal::RegExpParser::ParseRegExp(
-            CcTest::i_isolate(), &zone, &reader, false, false, &result));
+      CcTest::i_isolate(), &zone, &reader, JSRegExp::kNone, &result));
   CHECK(result.tree == NULL);
   CHECK(!result.error.is_null());
   v8::base::SmartArrayPointer<char> str = result.error->ToCString(ALLOW_NULLS);
@@ -523,7 +529,7 @@
   ZoneList<CharacterRange>* ranges =
       new(&zone) ZoneList<CharacterRange>(2, &zone);
   CharacterRange::AddClassEscape(c, ranges, &zone);
-  for (unsigned i = 0; i < (1 << 16); i++) {
+  for (uc32 i = 0; i < (1 << 16); i++) {
     bool in_class = false;
     for (int j = 0; !in_class && j < ranges->length(); j++) {
       CharacterRange& range = ranges->at(j);
@@ -550,17 +556,19 @@
   Isolate* isolate = CcTest::i_isolate();
   FlatStringReader reader(isolate, CStrVector(input));
   RegExpCompileData compile_data;
+  JSRegExp::Flags flags = JSRegExp::kNone;
+  if (multiline) flags = JSRegExp::kMultiline;
+  if (unicode) flags = JSRegExp::kUnicode;
   if (!v8::internal::RegExpParser::ParseRegExp(CcTest::i_isolate(), zone,
-                                               &reader, multiline, unicode,
-                                               &compile_data))
+                                               &reader, flags, &compile_data))
     return NULL;
   Handle<String> pattern = isolate->factory()
                                ->NewStringFromUtf8(CStrVector(input))
                                .ToHandleChecked();
   Handle<String> sample_subject =
       isolate->factory()->NewStringFromUtf8(CStrVector("")).ToHandleChecked();
-  RegExpEngine::Compile(isolate, zone, &compile_data, false, false, multiline,
-                        false, pattern, sample_subject, is_one_byte);
+  RegExpEngine::Compile(isolate, zone, &compile_data, flags, pattern,
+                        sample_subject, is_one_byte);
   return compile_data.node;
 }
 
@@ -678,7 +686,7 @@
   for (int i = 0; i < kRangeCount; i++) {
     uc16* range = ranges[i];
     for (int j = 0; j < 2 * kRangeSize; j += 2)
-      table.AddRange(CharacterRange(range[j], range[j + 1]), i, &zone);
+      table.AddRange(CharacterRange::Range(range[j], range[j + 1]), i, &zone);
   }
   // Check that the table looks as we would expect
   for (int p = 0; p < kLimit; p++) {
@@ -1178,16 +1186,16 @@
   m.WriteCurrentPositionToRegister(2, 0);
   m.AdvanceCurrentPosition(3);
   m.WriteCurrentPositionToRegister(3, 0);
-  m.CheckNotBackReferenceIgnoreCase(2, false, &fail);  // Match "AbC".
-  m.CheckNotBackReferenceIgnoreCase(2, false, &fail);  // Match "ABC".
+  m.CheckNotBackReferenceIgnoreCase(2, false, false, &fail);  // Match "AbC".
+  m.CheckNotBackReferenceIgnoreCase(2, false, false, &fail);  // Match "ABC".
   Label expected_fail;
-  m.CheckNotBackReferenceIgnoreCase(2, false, &expected_fail);
+  m.CheckNotBackReferenceIgnoreCase(2, false, false, &expected_fail);
   m.Bind(&fail);
   m.Fail();
 
   m.Bind(&expected_fail);
   m.AdvanceCurrentPosition(3);  // Skip "xYz"
-  m.CheckNotBackReferenceIgnoreCase(2, false, &succ);
+  m.CheckNotBackReferenceIgnoreCase(2, false, false, &succ);
   m.Fail();
 
   m.Bind(&succ);
@@ -1490,7 +1498,7 @@
       int from = PseudoRandom(t + 87, i + 25) % kLimit;
       int to = from + (PseudoRandom(i + 87, t + 25) % (kLimit / 20));
       if (to > kLimit) to = kLimit;
-      ranges->Add(CharacterRange(from, to), &zone);
+      ranges->Add(CharacterRange::Range(from, to), &zone);
     }
     DispatchTable table(&zone);
     DispatchTableConstructor cons(&table, false, &zone);
@@ -1507,7 +1515,7 @@
   Zone zone;
   ZoneList<CharacterRange>* ranges =
       new(&zone) ZoneList<CharacterRange>(1, &zone);
-  ranges->Add(CharacterRange(0xFFF0, 0xFFFE), &zone);
+  ranges->Add(CharacterRange::Range(0xFFF0, 0xFFFE), &zone);
   DispatchTable table(&zone);
   DispatchTableConstructor cons(&table, false, &zone);
   cons.set_choice_index(0);
@@ -1621,7 +1629,9 @@
   int count = expected.length();
   ZoneList<CharacterRange>* list =
       new(&zone) ZoneList<CharacterRange>(count, &zone);
-  input.AddCaseEquivalents(isolate, &zone, list, false);
+  list->Add(input, &zone);
+  CharacterRange::AddCaseEquivalents(isolate, &zone, list, false);
+  list->Remove(0);  // Remove the input before checking results.
   CHECK_EQ(count, list->length());
   for (int i = 0; i < list->length(); i++) {
     CHECK_EQ(expected[i].from(), list->at(i).from());
@@ -1645,31 +1655,33 @@
                                   CharacterRange::Singleton('A'));
   TestSimpleRangeCaseIndependence(isolate, CharacterRange::Singleton('z'),
                                   CharacterRange::Singleton('Z'));
-  TestSimpleRangeCaseIndependence(isolate, CharacterRange('a', 'z'),
-                                  CharacterRange('A', 'Z'));
-  TestSimpleRangeCaseIndependence(isolate, CharacterRange('c', 'f'),
-                                  CharacterRange('C', 'F'));
-  TestSimpleRangeCaseIndependence(isolate, CharacterRange('a', 'b'),
-                                  CharacterRange('A', 'B'));
-  TestSimpleRangeCaseIndependence(isolate, CharacterRange('y', 'z'),
-                                  CharacterRange('Y', 'Z'));
-  TestSimpleRangeCaseIndependence(isolate, CharacterRange('a' - 1, 'z' + 1),
-                                  CharacterRange('A', 'Z'));
-  TestSimpleRangeCaseIndependence(isolate, CharacterRange('A', 'Z'),
-                                  CharacterRange('a', 'z'));
-  TestSimpleRangeCaseIndependence(isolate, CharacterRange('C', 'F'),
-                                  CharacterRange('c', 'f'));
-  TestSimpleRangeCaseIndependence(isolate, CharacterRange('A' - 1, 'Z' + 1),
-                                  CharacterRange('a', 'z'));
+  TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('a', 'z'),
+                                  CharacterRange::Range('A', 'Z'));
+  TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('c', 'f'),
+                                  CharacterRange::Range('C', 'F'));
+  TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('a', 'b'),
+                                  CharacterRange::Range('A', 'B'));
+  TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('y', 'z'),
+                                  CharacterRange::Range('Y', 'Z'));
+  TestSimpleRangeCaseIndependence(isolate,
+                                  CharacterRange::Range('a' - 1, 'z' + 1),
+                                  CharacterRange::Range('A', 'Z'));
+  TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('A', 'Z'),
+                                  CharacterRange::Range('a', 'z'));
+  TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('C', 'F'),
+                                  CharacterRange::Range('c', 'f'));
+  TestSimpleRangeCaseIndependence(isolate,
+                                  CharacterRange::Range('A' - 1, 'Z' + 1),
+                                  CharacterRange::Range('a', 'z'));
   // Here we need to add [l-z] to complete the case independence of
   // [A-Za-z] but we expect [a-z] to be added since we always add a
   // whole block at a time.
-  TestSimpleRangeCaseIndependence(isolate, CharacterRange('A', 'k'),
-                                  CharacterRange('a', 'z'));
+  TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('A', 'k'),
+                                  CharacterRange::Range('a', 'z'));
 }
 
 
-static bool InClass(uc16 c, ZoneList<CharacterRange>* ranges) {
+static bool InClass(uc32 c, ZoneList<CharacterRange>* ranges) {
   if (ranges == NULL)
     return false;
   for (int i = 0; i < ranges->length(); i++) {
@@ -1681,29 +1693,46 @@
 }
 
 
-TEST(CharClassDifference) {
+TEST(UnicodeRangeSplitter) {
   Zone zone;
   ZoneList<CharacterRange>* base =
       new(&zone) ZoneList<CharacterRange>(1, &zone);
   base->Add(CharacterRange::Everything(), &zone);
-  Vector<const int> overlay = CharacterRange::GetWordBounds();
-  ZoneList<CharacterRange>* included = NULL;
-  ZoneList<CharacterRange>* excluded = NULL;
-  CharacterRange::Split(base, overlay, &included, &excluded, &zone);
-  for (int i = 0; i < (1 << 16); i++) {
-    bool in_base = InClass(i, base);
-    if (in_base) {
-      bool in_overlay = false;
-      for (int j = 0; !in_overlay && j < overlay.length(); j += 2) {
-        if (overlay[j] <= i && i < overlay[j+1])
-          in_overlay = true;
-      }
-      CHECK_EQ(in_overlay, InClass(i, included));
-      CHECK_EQ(!in_overlay, InClass(i, excluded));
-    } else {
-      CHECK(!InClass(i, included));
-      CHECK(!InClass(i, excluded));
-    }
+  UnicodeRangeSplitter splitter(&zone, base);
+  // BMP
+  for (uc32 c = 0; c < 0xd800; c++) {
+    CHECK(InClass(c, splitter.bmp()));
+    CHECK(!InClass(c, splitter.lead_surrogates()));
+    CHECK(!InClass(c, splitter.trail_surrogates()));
+    CHECK(!InClass(c, splitter.non_bmp()));
+  }
+  // Lead surrogates
+  for (uc32 c = 0xd800; c < 0xdbff; c++) {
+    CHECK(!InClass(c, splitter.bmp()));
+    CHECK(InClass(c, splitter.lead_surrogates()));
+    CHECK(!InClass(c, splitter.trail_surrogates()));
+    CHECK(!InClass(c, splitter.non_bmp()));
+  }
+  // Trail surrogates
+  for (uc32 c = 0xdc00; c < 0xdfff; c++) {
+    CHECK(!InClass(c, splitter.bmp()));
+    CHECK(!InClass(c, splitter.lead_surrogates()));
+    CHECK(InClass(c, splitter.trail_surrogates()));
+    CHECK(!InClass(c, splitter.non_bmp()));
+  }
+  // BMP
+  for (uc32 c = 0xe000; c < 0xffff; c++) {
+    CHECK(InClass(c, splitter.bmp()));
+    CHECK(!InClass(c, splitter.lead_surrogates()));
+    CHECK(!InClass(c, splitter.trail_surrogates()));
+    CHECK(!InClass(c, splitter.non_bmp()));
+  }
+  // Non-BMP
+  for (uc32 c = 0x10000; c < 0x10ffff; c++) {
+    CHECK(!InClass(c, splitter.bmp()));
+    CHECK(!InClass(c, splitter.lead_surrogates()));
+    CHECK(!InClass(c, splitter.trail_surrogates()));
+    CHECK(InClass(c, splitter.non_bmp()));
   }
 }
 
@@ -1714,9 +1743,9 @@
       new(&zone) ZoneList<CharacterRange>(4, &zone);
   CharacterSet set(list);
 
-  list->Add(CharacterRange(10, 20), &zone);
-  list->Add(CharacterRange(30, 40), &zone);
-  list->Add(CharacterRange(50, 60), &zone);
+  list->Add(CharacterRange::Range(10, 20), &zone);
+  list->Add(CharacterRange::Range(30, 40), &zone);
+  list->Add(CharacterRange::Range(50, 60), &zone);
   set.Canonicalize();
   CHECK_EQ(3, list->length());
   CHECK_EQ(10, list->at(0).from());
@@ -1727,9 +1756,9 @@
   CHECK_EQ(60, list->at(2).to());
 
   list->Rewind(0);
-  list->Add(CharacterRange(10, 20), &zone);
-  list->Add(CharacterRange(50, 60), &zone);
-  list->Add(CharacterRange(30, 40), &zone);
+  list->Add(CharacterRange::Range(10, 20), &zone);
+  list->Add(CharacterRange::Range(50, 60), &zone);
+  list->Add(CharacterRange::Range(30, 40), &zone);
   set.Canonicalize();
   CHECK_EQ(3, list->length());
   CHECK_EQ(10, list->at(0).from());
@@ -1740,11 +1769,11 @@
   CHECK_EQ(60, list->at(2).to());
 
   list->Rewind(0);
-  list->Add(CharacterRange(30, 40), &zone);
-  list->Add(CharacterRange(10, 20), &zone);
-  list->Add(CharacterRange(25, 25), &zone);
-  list->Add(CharacterRange(100, 100), &zone);
-  list->Add(CharacterRange(1, 1), &zone);
+  list->Add(CharacterRange::Range(30, 40), &zone);
+  list->Add(CharacterRange::Range(10, 20), &zone);
+  list->Add(CharacterRange::Range(25, 25), &zone);
+  list->Add(CharacterRange::Range(100, 100), &zone);
+  list->Add(CharacterRange::Range(1, 1), &zone);
   set.Canonicalize();
   CHECK_EQ(5, list->length());
   CHECK_EQ(1, list->at(0).from());
@@ -1759,9 +1788,9 @@
   CHECK_EQ(100, list->at(4).to());
 
   list->Rewind(0);
-  list->Add(CharacterRange(10, 19), &zone);
-  list->Add(CharacterRange(21, 30), &zone);
-  list->Add(CharacterRange(20, 20), &zone);
+  list->Add(CharacterRange::Range(10, 19), &zone);
+  list->Add(CharacterRange::Range(21, 30), &zone);
+  list->Add(CharacterRange::Range(20, 20), &zone);
   set.Canonicalize();
   CHECK_EQ(1, list->length());
   CHECK_EQ(10, list->at(0).from());
@@ -1938,3 +1967,26 @@
   CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]);
   CHECK(resultToStringError->IsObject());
 }
+
+class UncachedExternalString
+    : public v8::String::ExternalOneByteStringResource {
+ public:
+  const char* data() const override { return "abcdefghijklmnopqrstuvwxyz"; }
+  size_t length() const override { return 26; }
+  bool IsCompressible() const override { return true; }
+};
+
+TEST(UncachedExternalString) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  LocalContext env;
+  v8::Local<v8::String> external =
+      v8::String::NewExternalOneByte(isolate, new UncachedExternalString())
+          .ToLocalChecked();
+  CHECK(v8::Utils::OpenHandle(*external)->map() ==
+        CcTest::i_isolate()->heap()->short_external_one_byte_string_map());
+  v8::Local<v8::Object> global = env->Global();
+  global->Set(env.local(), v8_str("external"), external).FromJust();
+  CompileRun("var re = /y(.)/; re.test('ab');");
+  ExpectString("external.substring(1).match(re)[1]", "z");
+}
diff --git a/test/cctest/test-transitions.cc b/test/cctest/test-transitions.cc
index 8834f9a..b7eb50f 100644
--- a/test/cctest/test-transitions.cc
+++ b/test/cctest/test-transitions.cc
@@ -10,6 +10,7 @@
 #include "src/compilation-cache.h"
 #include "src/execution.h"
 #include "src/factory.h"
+#include "src/field-type.h"
 #include "src/global-handles.h"
 #include "test/cctest/cctest.h"
 
@@ -51,13 +52,13 @@
 
   Handle<Map> map0 = Map::Create(isolate, 0);
   Handle<Map> map1 =
-      Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate),
-                         attributes, Representation::Tagged(),
-                         OMIT_TRANSITION).ToHandleChecked();
+      Map::CopyWithField(map0, name1, handle(FieldType::Any(), isolate),
+                         attributes, Representation::Tagged(), OMIT_TRANSITION)
+          .ToHandleChecked();
   Handle<Map> map2 =
-      Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate),
-                         attributes, Representation::Tagged(),
-                         OMIT_TRANSITION).ToHandleChecked();
+      Map::CopyWithField(map0, name2, handle(FieldType::Any(), isolate),
+                         attributes, Representation::Tagged(), OMIT_TRANSITION)
+          .ToHandleChecked();
 
   CHECK(map0->raw_transitions()->IsSmi());
 
@@ -102,13 +103,13 @@
 
   Handle<Map> map0 = Map::Create(isolate, 0);
   Handle<Map> map1 =
-      Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate),
-                         attributes, Representation::Tagged(),
-                         OMIT_TRANSITION).ToHandleChecked();
+      Map::CopyWithField(map0, name1, handle(FieldType::Any(), isolate),
+                         attributes, Representation::Tagged(), OMIT_TRANSITION)
+          .ToHandleChecked();
   Handle<Map> map2 =
-      Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate),
-                         attributes, Representation::Tagged(),
-                         OMIT_TRANSITION).ToHandleChecked();
+      Map::CopyWithField(map0, name2, handle(FieldType::Any(), isolate),
+                         attributes, Representation::Tagged(), OMIT_TRANSITION)
+          .ToHandleChecked();
 
   CHECK(map0->raw_transitions()->IsSmi());
 
@@ -159,10 +160,10 @@
     EmbeddedVector<char, 64> buffer;
     SNPrintF(buffer, "prop%d", i);
     Handle<String> name = factory->InternalizeUtf8String(buffer.start());
-    Handle<Map> map =
-        Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
-                           attributes, Representation::Tagged(),
-                           OMIT_TRANSITION).ToHandleChecked();
+    Handle<Map> map = Map::CopyWithField(
+                          map0, name, handle(FieldType::Any(), isolate),
+                          attributes, Representation::Tagged(), OMIT_TRANSITION)
+                          .ToHandleChecked();
     names[i] = name;
     maps[i] = map;
 
@@ -208,10 +209,10 @@
   for (int i = 0; i < ATTRS_COUNT; i++) {
     PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
 
-    Handle<Map> map =
-        Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
-                           attributes, Representation::Tagged(),
-                           OMIT_TRANSITION).ToHandleChecked();
+    Handle<Map> map = Map::CopyWithField(
+                          map0, name, handle(FieldType::Any(), isolate),
+                          attributes, Representation::Tagged(), OMIT_TRANSITION)
+                          .ToHandleChecked();
     attr_maps[i] = map;
 
     TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
@@ -252,9 +253,9 @@
     SNPrintF(buffer, "prop%d", i);
     Handle<String> name = factory->InternalizeUtf8String(buffer.start());
     Handle<Map> map =
-        Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate), NONE,
-                           Representation::Tagged(),
-                           OMIT_TRANSITION).ToHandleChecked();
+        Map::CopyWithField(map0, name, handle(FieldType::Any(), isolate), NONE,
+                           Representation::Tagged(), OMIT_TRANSITION)
+            .ToHandleChecked();
     names[i] = name;
     maps[i] = map;
 
@@ -270,10 +271,10 @@
   for (int i = 0; i < ATTRS_COUNT; i++) {
     PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
 
-    Handle<Map> map =
-        Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
-                           attributes, Representation::Tagged(),
-                           OMIT_TRANSITION).ToHandleChecked();
+    Handle<Map> map = Map::CopyWithField(
+                          map0, name, handle(FieldType::Any(), isolate),
+                          attributes, Representation::Tagged(), OMIT_TRANSITION)
+                          .ToHandleChecked();
     attr_maps[i] = map;
 
     TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc
index 4549654..2e658b0 100644
--- a/test/cctest/test-types.cc
+++ b/test/cctest/test-types.cc
@@ -27,109 +27,43 @@
 
 typedef uint32_t bitset;
 
-
-struct ZoneRep {
-  typedef void* Struct;
-
-  static bool IsStruct(Type* t, int tag) {
-    return !IsBitset(t) && reinterpret_cast<intptr_t>(AsStruct(t)[0]) == tag;
-  }
-  static bool IsBitset(Type* t) { return reinterpret_cast<uintptr_t>(t) & 1; }
-  // HACK: the number 5 below is the value of StructuralType::kUnionTag.
-  static bool IsUnion(Type* t) { return t->IsUnionForTesting(); }
-
-  static Struct* AsStruct(Type* t) {
-    return reinterpret_cast<Struct*>(t);
-  }
-  static bitset AsBitset(Type* t) {
-    return static_cast<bitset>(reinterpret_cast<uintptr_t>(t) ^ 1u);
-  }
-  static Struct* AsUnion(Type* t) {
-    return AsStruct(t);
-  }
-  static int Length(Struct* structured) {
-    return static_cast<int>(reinterpret_cast<intptr_t>(structured[1]));
-  }
-
-  static Zone* ToRegion(Zone* zone, Isolate* isolate) { return zone; }
-
-  struct BitsetType : Type::BitsetType {
-    using Type::BitsetType::New;
-    using Type::BitsetType::Glb;
-    using Type::BitsetType::Lub;
-    using Type::BitsetType::IsInhabited;
-  };
-};
-
-
-struct HeapRep {
-  typedef FixedArray Struct;
-
-  static bool IsStruct(Handle<HeapType> t, int tag) {
-    return t->IsFixedArray() && Smi::cast(AsStruct(t)->get(0))->value() == tag;
-  }
-  static bool IsBitset(Handle<HeapType> t) { return t->IsSmi(); }
-  // HACK: the number 5 below is the value of StructuralType::kUnionTag.
-  static bool IsUnion(Handle<HeapType> t) { return t->IsUnionForTesting(); }
-
-  static Struct* AsStruct(Handle<HeapType> t) { return FixedArray::cast(*t); }
-  static bitset AsBitset(Handle<HeapType> t) {
-    return static_cast<bitset>(reinterpret_cast<uintptr_t>(*t));
-  }
-  static Struct* AsUnion(Handle<HeapType> t) { return AsStruct(t); }
-  static int Length(Struct* structured) { return structured->length() - 1; }
-
-  static Isolate* ToRegion(Zone* zone, Isolate* isolate) { return isolate; }
-
-  struct BitsetType : HeapType::BitsetType {
-    using HeapType::BitsetType::New;
-    using HeapType::BitsetType::Glb;
-    using HeapType::BitsetType::Lub;
-    using HeapType::BitsetType::IsInhabited;
-    static bitset Glb(Handle<HeapType> type) { return Glb(*type); }
-    static bitset Lub(Handle<HeapType> type) { return Lub(*type); }
-  };
-};
-
-
-template<class Type, class TypeHandle, class Region, class Rep>
-struct Tests : Rep {
-  typedef Types<Type, TypeHandle, Region> TypesInstance;
-  typedef typename TypesInstance::TypeVector::iterator TypeIterator;
-  typedef typename TypesInstance::MapVector::iterator MapIterator;
-  typedef typename TypesInstance::ValueVector::iterator ValueIterator;
+struct Tests {
+  typedef Types::TypeVector::iterator TypeIterator;
+  typedef Types::MapVector::iterator MapIterator;
+  typedef Types::ValueVector::iterator ValueIterator;
 
   Isolate* isolate;
   HandleScope scope;
   Zone zone;
-  TypesInstance T;
+  Types T;
 
   Tests()
       : isolate(CcTest::InitIsolateOnce()),
         scope(isolate),
         zone(),
-        T(Rep::ToRegion(&zone, isolate), isolate,
-          isolate->random_number_generator()) {}
+        T(&zone, isolate, isolate->random_number_generator()) {}
 
-  bool Equal(TypeHandle type1, TypeHandle type2) {
-    return
-        type1->Equals(type2) &&
-        this->IsBitset(type1) == this->IsBitset(type2) &&
-        this->IsUnion(type1) == this->IsUnion(type2) &&
-        type1->NumClasses() == type2->NumClasses() &&
-        type1->NumConstants() == type2->NumConstants() &&
-        (!this->IsBitset(type1) ||
-          this->AsBitset(type1) == this->AsBitset(type2)) &&
-        (!this->IsUnion(type1) ||
-          this->Length(this->AsUnion(type1)) ==
-              this->Length(this->AsUnion(type2)));
+  bool IsBitset(Type* type) { return type->IsBitsetForTesting(); }
+  bool IsUnion(Type* type) { return type->IsUnionForTesting(); }
+  BitsetType::bitset AsBitset(Type* type) { return type->AsBitsetForTesting(); }
+  UnionType* AsUnion(Type* type) { return type->AsUnionForTesting(); }
+
+  bool Equal(Type* type1, Type* type2) {
+    return type1->Equals(type2) &&
+           this->IsBitset(type1) == this->IsBitset(type2) &&
+           this->IsUnion(type1) == this->IsUnion(type2) &&
+           type1->NumClasses() == type2->NumClasses() &&
+           type1->NumConstants() == type2->NumConstants() &&
+           (!this->IsBitset(type1) ||
+            this->AsBitset(type1) == this->AsBitset(type2)) &&
+           (!this->IsUnion(type1) ||
+            this->AsUnion(type1)->LengthForTesting() ==
+                this->AsUnion(type2)->LengthForTesting());
   }
 
-  void CheckEqual(TypeHandle type1, TypeHandle type2) {
-    CHECK(Equal(type1, type2));
-  }
+  void CheckEqual(Type* type1, Type* type2) { CHECK(Equal(type1, type2)); }
 
-  void CheckSub(TypeHandle type1, TypeHandle type2) {
+  void CheckSub(Type* type1, Type* type2) {
     CHECK(type1->Is(type2));
     CHECK(!type2->Is(type1));
     if (this->IsBitset(type1) && this->IsBitset(type2)) {
@@ -137,7 +71,7 @@
     }
   }
 
-  void CheckSubOrEqual(TypeHandle type1, TypeHandle type2) {
+  void CheckSubOrEqual(Type* type1, Type* type2) {
     CHECK(type1->Is(type2));
     if (this->IsBitset(type1) && this->IsBitset(type2)) {
       CHECK((this->AsBitset(type1) | this->AsBitset(type2))
@@ -145,7 +79,7 @@
     }
   }
 
-  void CheckUnordered(TypeHandle type1, TypeHandle type2) {
+  void CheckUnordered(Type* type1, Type* type2) {
     CHECK(!type1->Is(type2));
     CHECK(!type2->Is(type1));
     if (this->IsBitset(type1) && this->IsBitset(type2)) {
@@ -153,12 +87,12 @@
     }
   }
 
-  void CheckOverlap(TypeHandle type1, TypeHandle type2) {
+  void CheckOverlap(Type* type1, Type* type2) {
     CHECK(type1->Maybe(type2));
     CHECK(type2->Maybe(type1));
   }
 
-  void CheckDisjoint(TypeHandle type1, TypeHandle type2) {
+  void CheckDisjoint(Type* type1, Type* type2) {
     CHECK(!type1->Is(type2));
     CHECK(!type2->Is(type1));
     CHECK(!type1->Maybe(type2));
@@ -167,7 +101,7 @@
 
   void IsSomeType() {
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle t = *it;
+      Type* t = *it;
       CHECK(1 ==
           this->IsBitset(t) + t->IsClass() + t->IsConstant() + t->IsRange() +
           this->IsUnion(t) + t->IsArray() + t->IsFunction() + t->IsContext());
@@ -185,9 +119,9 @@
     // Union(T1, T2) is bitset for bitsets T1,T2
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle union12 = T.Union(type1, type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* union12 = T.Union(type1, type2);
         CHECK(!(this->IsBitset(type1) && this->IsBitset(type2)) ||
               this->IsBitset(union12));
       }
@@ -196,9 +130,9 @@
     // Intersect(T1, T2) is bitset for bitsets T1,T2
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle intersect12 = T.Intersect(type1, type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* intersect12 = T.Intersect(type1, type2);
         CHECK(!(this->IsBitset(type1) && this->IsBitset(type2)) ||
               this->IsBitset(intersect12));
       }
@@ -207,9 +141,9 @@
     // Union(T1, T2) is bitset if T2 is bitset and T1->Is(T2)
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle union12 = T.Union(type1, type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* union12 = T.Union(type1, type2);
         CHECK(!(this->IsBitset(type2) && type1->Is(type2)) ||
               this->IsBitset(union12));
       }
@@ -218,9 +152,9 @@
     // Union(T1, T2) is bitwise disjunction for bitsets T1,T2
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle union12 = T.Union(type1, type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* union12 = T.Union(type1, type2);
         if (this->IsBitset(type1) && this->IsBitset(type2)) {
           CHECK(
               (this->AsBitset(type1) | this->AsBitset(type2)) ==
@@ -232,10 +166,10 @@
     // Intersect(T1, T2) is bitwise conjunction for bitsets T1,T2 (modulo None)
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         if (this->IsBitset(type1) && this->IsBitset(type2)) {
-          TypeHandle intersect12 = T.Intersect(type1, type2);
+          Type* intersect12 = T.Intersect(type1, type2);
           bitset bits = this->AsBitset(type1) & this->AsBitset(type2);
           CHECK(bits == this->AsBitset(intersect12));
         }
@@ -251,28 +185,26 @@
       counter++;
       printf("Counter: %i\n", counter);
       fflush(stdout);
-      TypeHandle type1 = *it1;
-      TypeHandle representation = T.Representation(type1);
-      TypeHandle semantic = T.Semantic(type1);
-      TypeHandle composed = T.Union(representation, semantic);
+      Type* type1 = *it1;
+      Type* representation = T.Representation(type1);
+      Type* semantic = T.Semantic(type1);
+      Type* composed = T.Union(representation, semantic);
       CHECK(type1->Equals(composed));
     }
 
     // Pointwiseness of Union.
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle representation1 = T.Representation(type1);
-        TypeHandle semantic1 = T.Semantic(type1);
-        TypeHandle representation2 = T.Representation(type2);
-        TypeHandle semantic2 = T.Semantic(type2);
-        TypeHandle direct_union = T.Union(type1, type2);
-        TypeHandle representation_union =
-            T.Union(representation1, representation2);
-        TypeHandle semantic_union = T.Union(semantic1, semantic2);
-        TypeHandle composed_union =
-            T.Union(representation_union, semantic_union);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* representation1 = T.Representation(type1);
+        Type* semantic1 = T.Semantic(type1);
+        Type* representation2 = T.Representation(type2);
+        Type* semantic2 = T.Semantic(type2);
+        Type* direct_union = T.Union(type1, type2);
+        Type* representation_union = T.Union(representation1, representation2);
+        Type* semantic_union = T.Union(semantic1, semantic2);
+        Type* composed_union = T.Union(representation_union, semantic_union);
         CHECK(direct_union->Equals(composed_union));
       }
     }
@@ -280,17 +212,17 @@
     // Pointwiseness of Intersect.
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle representation1 = T.Representation(type1);
-        TypeHandle semantic1 = T.Semantic(type1);
-        TypeHandle representation2 = T.Representation(type2);
-        TypeHandle semantic2 = T.Semantic(type2);
-        TypeHandle direct_intersection = T.Intersect(type1, type2);
-        TypeHandle representation_intersection =
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* representation1 = T.Representation(type1);
+        Type* semantic1 = T.Semantic(type1);
+        Type* representation2 = T.Representation(type2);
+        Type* semantic2 = T.Semantic(type2);
+        Type* direct_intersection = T.Intersect(type1, type2);
+        Type* representation_intersection =
             T.Intersect(representation1, representation2);
-        TypeHandle semantic_intersection = T.Intersect(semantic1, semantic2);
-        TypeHandle composed_intersection =
+        Type* semantic_intersection = T.Intersect(semantic1, semantic2);
+        Type* composed_intersection =
             T.Union(representation_intersection, semantic_intersection);
         CHECK(direct_intersection->Equals(composed_intersection));
       }
@@ -299,12 +231,12 @@
     // Pointwiseness of Is.
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle representation1 = T.Representation(type1);
-        TypeHandle semantic1 = T.Semantic(type1);
-        TypeHandle representation2 = T.Representation(type2);
-        TypeHandle semantic2 = T.Semantic(type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* representation1 = T.Representation(type1);
+        Type* semantic1 = T.Semantic(type1);
+        Type* representation2 = T.Representation(type2);
+        Type* semantic2 = T.Semantic(type2);
         bool representation_is = representation1->Is(representation2);
         bool semantic_is = semantic1->Is(semantic2);
         bool direct_is = type1->Is(type2);
@@ -317,14 +249,14 @@
     // Constructor
     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
       Handle<i::Map> map = *mt;
-      TypeHandle type = T.Class(map);
+      Type* type = T.Class(map);
       CHECK(type->IsClass());
     }
 
     // Map attribute
     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
       Handle<i::Map> map = *mt;
-      TypeHandle type = T.Class(map);
+      Type* type = T.Class(map);
       CHECK(*map == *type->AsClass()->Map());
     }
 
@@ -333,8 +265,8 @@
       for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
         Handle<i::Map> map1 = *mt1;
         Handle<i::Map> map2 = *mt2;
-        TypeHandle type1 = T.Class(map1);
-        TypeHandle type2 = T.Class(map2);
+        Type* type1 = T.Class(map1);
+        Type* type2 = T.Class(map2);
         CHECK(Equal(type1, type2) == (*map1 == *map2));
       }
     }
@@ -344,14 +276,14 @@
     // Constructor
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       Handle<i::Object> value = *vt;
-      TypeHandle type = T.Constant(value);
+      Type* type = T.Constant(value);
       CHECK(type->IsConstant());
     }
 
     // Value attribute
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       Handle<i::Object> value = *vt;
-      TypeHandle type = T.Constant(value);
+      Type* type = T.Constant(value);
       CHECK(*value == *type->AsConstant()->Value());
     }
 
@@ -360,8 +292,8 @@
       for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
         Handle<i::Object> value1 = *vt1;
         Handle<i::Object> value2 = *vt2;
-        TypeHandle type1 = T.Constant(value1);
-        TypeHandle type2 = T.Constant(value2);
+        Type* type1 = T.Constant(value1);
+        Type* type2 = T.Constant(value2);
         CHECK(Equal(type1, type2) == (*value1 == *value2));
       }
     }
@@ -424,7 +356,7 @@
         double min = (*i)->Number();
         double max = (*j)->Number();
         if (min > max) std::swap(min, max);
-        TypeHandle type = T.Range(min, max);
+        Type* type = T.Range(min, max);
         CHECK(type->IsRange());
       }
     }
@@ -435,7 +367,7 @@
         double min = (*i)->Number();
         double max = (*j)->Number();
         if (min > max) std::swap(min, max);
-        TypeHandle type = T.Range(min, max);
+        Type* type = T.Range(min, max);
         CHECK(min == type->AsRange()->Min());
         CHECK(max == type->AsRange()->Max());
       }
@@ -457,8 +389,8 @@
             double max2 = (*j2)->Number();
             if (min1 > max1) std::swap(min1, max1);
             if (min2 > max2) std::swap(min2, max2);
-            TypeHandle type1 = T.Range(min1, max1);
-            TypeHandle type2 = T.Range(min2, max2);
+            Type* type1 = T.Range(min1, max1);
+            Type* type2 = T.Range(min2, max2);
             CHECK(Equal(type1, type2) == (min1 == min2 && max1 == max2));
           }
         }
@@ -469,25 +401,25 @@
   void Context() {
     // Constructor
     for (int i = 0; i < 20; ++i) {
-      TypeHandle type = T.Random();
-      TypeHandle context = T.Context(type);
-      CHECK(context->Iscontext());
+      Type* type = T.Random();
+      Type* context = T.Context(type);
+      CHECK(context->IsContext());
     }
 
     // Attributes
     for (int i = 0; i < 20; ++i) {
-      TypeHandle type = T.Random();
-      TypeHandle context = T.Context(type);
+      Type* type = T.Random();
+      Type* context = T.Context(type);
       CheckEqual(type, context->AsContext()->Outer());
     }
 
     // Functionality & Injectivity: Context(T1) = Context(T2) iff T1 = T2
     for (int i = 0; i < 20; ++i) {
       for (int j = 0; j < 20; ++j) {
-        TypeHandle type1 = T.Random();
-        TypeHandle type2 = T.Random();
-        TypeHandle context1 = T.Context(type1);
-        TypeHandle context2 = T.Context(type2);
+        Type* type1 = T.Random();
+        Type* type2 = T.Random();
+        Type* context1 = T.Context(type1);
+        Type* context2 = T.Context(type2);
         CHECK(Equal(context1, context2) == Equal(type1, type2));
       }
     }
@@ -496,25 +428,25 @@
   void Array() {
     // Constructor
     for (int i = 0; i < 20; ++i) {
-      TypeHandle type = T.Random();
-      TypeHandle array = T.Array1(type);
+      Type* type = T.Random();
+      Type* array = T.Array1(type);
       CHECK(array->IsArray());
     }
 
     // Attributes
     for (int i = 0; i < 20; ++i) {
-      TypeHandle type = T.Random();
-      TypeHandle array = T.Array1(type);
+      Type* type = T.Random();
+      Type* array = T.Array1(type);
       CheckEqual(type, array->AsArray()->Element());
     }
 
     // Functionality & Injectivity: Array(T1) = Array(T2) iff T1 = T2
     for (int i = 0; i < 20; ++i) {
       for (int j = 0; j < 20; ++j) {
-        TypeHandle type1 = T.Random();
-        TypeHandle type2 = T.Random();
-        TypeHandle array1 = T.Array1(type1);
-        TypeHandle array2 = T.Array1(type2);
+        Type* type1 = T.Random();
+        Type* type2 = T.Random();
+        Type* array1 = T.Array1(type1);
+        Type* array2 = T.Array1(type2);
         CHECK(Equal(array1, array2) == Equal(type1, type2));
       }
     }
@@ -525,12 +457,12 @@
     for (int i = 0; i < 20; ++i) {
       for (int j = 0; j < 20; ++j) {
         for (int k = 0; k < 20; ++k) {
-          TypeHandle type1 = T.Random();
-          TypeHandle type2 = T.Random();
-          TypeHandle type3 = T.Random();
-          TypeHandle function0 = T.Function0(type1, type2);
-          TypeHandle function1 = T.Function1(type1, type2, type3);
-          TypeHandle function2 = T.Function2(type1, type2, type3);
+          Type* type1 = T.Random();
+          Type* type2 = T.Random();
+          Type* type3 = T.Random();
+          Type* function0 = T.Function0(type1, type2);
+          Type* function1 = T.Function1(type1, type2, type3);
+          Type* function2 = T.Function2(type1, type2, type3);
           CHECK(function0->IsFunction());
           CHECK(function1->IsFunction());
           CHECK(function2->IsFunction());
@@ -542,12 +474,12 @@
     for (int i = 0; i < 20; ++i) {
       for (int j = 0; j < 20; ++j) {
         for (int k = 0; k < 20; ++k) {
-          TypeHandle type1 = T.Random();
-          TypeHandle type2 = T.Random();
-          TypeHandle type3 = T.Random();
-          TypeHandle function0 = T.Function0(type1, type2);
-          TypeHandle function1 = T.Function1(type1, type2, type3);
-          TypeHandle function2 = T.Function2(type1, type2, type3);
+          Type* type1 = T.Random();
+          Type* type2 = T.Random();
+          Type* type3 = T.Random();
+          Type* function0 = T.Function0(type1, type2);
+          Type* function1 = T.Function1(type1, type2, type3);
+          Type* function2 = T.Function2(type1, type2, type3);
           CHECK_EQ(0, function0->AsFunction()->Arity());
           CHECK_EQ(1, function1->AsFunction()->Arity());
           CHECK_EQ(2, function2->AsFunction()->Arity());
@@ -568,17 +500,17 @@
     for (int i = 0; i < 20; ++i) {
       for (int j = 0; j < 20; ++j) {
         for (int k = 0; k < 20; ++k) {
-          TypeHandle type1 = T.Random();
-          TypeHandle type2 = T.Random();
-          TypeHandle type3 = T.Random();
-          TypeHandle function01 = T.Function0(type1, type2);
-          TypeHandle function02 = T.Function0(type1, type3);
-          TypeHandle function03 = T.Function0(type3, type2);
-          TypeHandle function11 = T.Function1(type1, type2, type2);
-          TypeHandle function12 = T.Function1(type1, type2, type3);
-          TypeHandle function21 = T.Function2(type1, type2, type2);
-          TypeHandle function22 = T.Function2(type1, type2, type3);
-          TypeHandle function23 = T.Function2(type1, type3, type2);
+          Type* type1 = T.Random();
+          Type* type2 = T.Random();
+          Type* type3 = T.Random();
+          Type* function01 = T.Function0(type1, type2);
+          Type* function02 = T.Function0(type1, type3);
+          Type* function03 = T.Function0(type3, type2);
+          Type* function11 = T.Function1(type1, type2, type2);
+          Type* function12 = T.Function1(type1, type2, type3);
+          Type* function21 = T.Function2(type1, type2, type2);
+          Type* function22 = T.Function2(type1, type2, type3);
+          Type* function23 = T.Function2(type1, type3, type2);
           CHECK(Equal(function01, function02) == Equal(type2, type3));
           CHECK(Equal(function01, function03) == Equal(type1, type3));
           CHECK(Equal(function11, function12) == Equal(type2, type3));
@@ -593,8 +525,8 @@
     // Constant(V)->Is(Of(V))
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       Handle<i::Object> value = *vt;
-      TypeHandle const_type = T.Constant(value);
-      TypeHandle of_type = T.Of(value);
+      Type* const_type = T.Constant(value);
+      Type* of_type = T.Of(value);
       CHECK(const_type->Is(of_type));
     }
 
@@ -602,9 +534,9 @@
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
         Handle<i::Object> value = *vt;
-        TypeHandle type = *it;
-        TypeHandle const_type = T.Constant(value);
-        TypeHandle of_type = T.Of(value);
+        Type* type = *it;
+        Type* const_type = T.Constant(value);
+        Type* of_type = T.Of(value);
         CHECK(!of_type->Is(type) || const_type->Is(type));
       }
     }
@@ -613,9 +545,9 @@
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
         Handle<i::Object> value = *vt;
-        TypeHandle type = *it;
-        TypeHandle const_type = T.Constant(value);
-        TypeHandle of_type = T.Of(value);
+        Type* type = *it;
+        Type* const_type = T.Constant(value);
+        Type* of_type = T.Of(value);
         CHECK(!const_type->Is(type) ||
               of_type->Is(type) || type->Maybe(const_type));
       }
@@ -626,16 +558,16 @@
     // Constant(V)->NowIs(NowOf(V))
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       Handle<i::Object> value = *vt;
-      TypeHandle const_type = T.Constant(value);
-      TypeHandle nowof_type = T.NowOf(value);
+      Type* const_type = T.Constant(value);
+      Type* nowof_type = T.NowOf(value);
       CHECK(const_type->NowIs(nowof_type));
     }
 
     // NowOf(V)->Is(Of(V))
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       Handle<i::Object> value = *vt;
-      TypeHandle nowof_type = T.NowOf(value);
-      TypeHandle of_type = T.Of(value);
+      Type* nowof_type = T.NowOf(value);
+      Type* of_type = T.Of(value);
       CHECK(nowof_type->Is(of_type));
     }
 
@@ -643,9 +575,9 @@
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
         Handle<i::Object> value = *vt;
-        TypeHandle type = *it;
-        TypeHandle const_type = T.Constant(value);
-        TypeHandle nowof_type = T.NowOf(value);
+        Type* type = *it;
+        Type* const_type = T.Constant(value);
+        Type* nowof_type = T.NowOf(value);
         CHECK(!nowof_type->NowIs(type) || const_type->NowIs(type));
       }
     }
@@ -655,9 +587,9 @@
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
         Handle<i::Object> value = *vt;
-        TypeHandle type = *it;
-        TypeHandle const_type = T.Constant(value);
-        TypeHandle nowof_type = T.NowOf(value);
+        Type* type = *it;
+        Type* const_type = T.Constant(value);
+        Type* nowof_type = T.NowOf(value);
         CHECK(!const_type->NowIs(type) ||
               nowof_type->NowIs(type) || type->Maybe(const_type));
       }
@@ -668,9 +600,9 @@
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
         Handle<i::Object> value = *vt;
-        TypeHandle type = *it;
-        TypeHandle const_type = T.Constant(value);
-        TypeHandle nowof_type = T.NowOf(value);
+        Type* type = *it;
+        Type* const_type = T.Constant(value);
+        Type* nowof_type = T.NowOf(value);
         CHECK(!const_type->Is(type) ||
               nowof_type->Is(type) || type->Maybe(const_type));
       }
@@ -682,10 +614,10 @@
     // TODO(neis): Need to ignore representation for this to be true.
     /*
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       if (this->IsBitset(type) && type->Is(T.Number) &&
           !type->Is(T.None) && !type->Is(T.NaN)) {
-        TypeHandle range = T.Range(
+        Type* range = T.Range(
             isolate->factory()->NewNumber(type->Min()),
             isolate->factory()->NewNumber(type->Max()));
         CHECK(range->Is(type));
@@ -695,7 +627,7 @@
 
     // If b is regular numeric bitset, then b->Min() and b->Max() are integers.
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       if (this->IsBitset(type) && type->Is(T.Number) && !type->Is(T.NaN)) {
         CHECK(IsInteger(type->Min()) && IsInteger(type->Max()));
       }
@@ -705,8 +637,8 @@
     // b1->Min() >= b2->Min() and b1->Max() <= b2->Max().
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         if (this->IsBitset(type1) && type1->Is(type2) && type2->Is(T.Number) &&
             !type1->Is(T.NaN) && !type2->Is(T.NaN)) {
           CHECK(type1->Min() >= type2->Min());
@@ -717,10 +649,9 @@
 
     // Lub(Range(x,y))->Min() <= x and y <= Lub(Range(x,y))->Max()
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       if (type->IsRange()) {
-        TypeHandle lub = Rep::BitsetType::New(
-            Rep::BitsetType::Lub(type), T.region());
+        Type* lub = BitsetType::NewForTesting(BitsetType::Lub(type));
         CHECK(lub->Min() <= type->Min() && type->Max() <= lub->Max());
       }
     }
@@ -728,7 +659,7 @@
     // Rangification: If T->Is(Range(-inf,+inf)) and T is inhabited, then
     // T->Is(Range(T->Min(), T->Max())).
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(!type->Is(T.Integer) || !type->IsInhabited() ||
             type->Is(T.Range(type->Min(), type->Max())));
     }
@@ -737,19 +668,17 @@
   void BitsetGlb() {
     // Lower: (T->BitsetGlb())->Is(T)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
-      TypeHandle glb =
-          Rep::BitsetType::New(Rep::BitsetType::Glb(type), T.region());
+      Type* type = *it;
+      Type* glb = BitsetType::NewForTesting(BitsetType::Glb(type));
       CHECK(glb->Is(type));
     }
 
     // Greatest: If T1->IsBitset() and T1->Is(T2), then T1->Is(T2->BitsetGlb())
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle glb2 =
-            Rep::BitsetType::New(Rep::BitsetType::Glb(type2), T.region());
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* glb2 = BitsetType::NewForTesting(BitsetType::Glb(type2));
         CHECK(!this->IsBitset(type1) || !type1->Is(type2) || type1->Is(glb2));
       }
     }
@@ -757,12 +686,10 @@
     // Monotonicity: T1->Is(T2) implies (T1->BitsetGlb())->Is(T2->BitsetGlb())
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle glb1 =
-            Rep::BitsetType::New(Rep::BitsetType::Glb(type1), T.region());
-        TypeHandle glb2 =
-            Rep::BitsetType::New(Rep::BitsetType::Glb(type2), T.region());
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* glb1 = BitsetType::NewForTesting(BitsetType::Glb(type1));
+        Type* glb2 = BitsetType::NewForTesting(BitsetType::Glb(type2));
         CHECK(!type1->Is(type2) || glb1->Is(glb2));
       }
     }
@@ -771,19 +698,17 @@
   void BitsetLub() {
     // Upper: T->Is(T->BitsetLub())
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
-      TypeHandle lub =
-          Rep::BitsetType::New(Rep::BitsetType::Lub(type), T.region());
+      Type* type = *it;
+      Type* lub = BitsetType::NewForTesting(BitsetType::Lub(type));
       CHECK(type->Is(lub));
     }
 
     // Least: If T2->IsBitset() and T1->Is(T2), then (T1->BitsetLub())->Is(T2)
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle lub1 =
-            Rep::BitsetType::New(Rep::BitsetType::Lub(type1), T.region());
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* lub1 = BitsetType::NewForTesting(BitsetType::Lub(type1));
         CHECK(!this->IsBitset(type2) || !type1->Is(type2) || lub1->Is(type2));
       }
     }
@@ -791,12 +716,10 @@
     // Monotonicity: T1->Is(T2) implies (T1->BitsetLub())->Is(T2->BitsetLub())
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle lub1 =
-            Rep::BitsetType::New(Rep::BitsetType::Lub(type1), T.region());
-        TypeHandle lub2 =
-            Rep::BitsetType::New(Rep::BitsetType::Lub(type2), T.region());
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* lub1 = BitsetType::NewForTesting(BitsetType::Lub(type1));
+        Type* lub2 = BitsetType::NewForTesting(BitsetType::Lub(type2));
         CHECK(!type1->Is(type2) || lub1->Is(lub2));
       }
     }
@@ -805,31 +728,31 @@
   void Is1() {
     // Least Element (Bottom): None->Is(T)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(T.None->Is(type));
     }
 
     // Greatest Element (Top): T->Is(Any)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(type->Is(T.Any));
     }
 
     // Bottom Uniqueness: T->Is(None) implies T = None
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       if (type->Is(T.None)) CheckEqual(type, T.None);
     }
 
     // Top Uniqueness: Any->Is(T) implies T = Any
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       if (T.Any->Is(type)) CheckEqual(type, T.Any);
     }
 
     // Reflexivity: T->Is(T)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(type->Is(type));
     }
 
@@ -837,9 +760,9 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
           CHECK(!(type1->Is(type2) && type2->Is(type3)) || type1->Is(type3));
         }
       }
@@ -848,8 +771,8 @@
     // Antisymmetry: T1->Is(T2) and T2->Is(T1) iff T1 = T2
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         CHECK((type1->Is(type2) && type2->Is(type1)) == Equal(type1, type2));
       }
     }
@@ -857,8 +780,8 @@
     // (In-)Compatibilities.
     for (TypeIterator i = T.types.begin(); i != T.types.end(); ++i) {
       for (TypeIterator j = T.types.begin(); j != T.types.end(); ++j) {
-        TypeHandle type1 = *i;
-        TypeHandle type2 = *j;
+        Type* type1 = *i;
+        Type* type2 = *j;
         CHECK(!type1->Is(type2) || this->IsBitset(type2) ||
               this->IsUnion(type2) || this->IsUnion(type1) ||
               (type1->IsClass() && type2->IsClass()) ||
@@ -880,8 +803,8 @@
       for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
         Handle<i::Map> map1 = *mt1;
         Handle<i::Map> map2 = *mt2;
-        TypeHandle class_type1 = T.Class(map1);
-        TypeHandle class_type2 = T.Class(map2);
+        Type* class_type1 = T.Class(map1);
+        Type* class_type2 = T.Class(map2);
         CHECK(class_type1->Is(class_type2) == (*map1 == *map2));
       }
     }
@@ -901,8 +824,8 @@
             double max2 = (*j2)->Number();
             if (min1 > max1) std::swap(min1, max1);
             if (min2 > max2) std::swap(min2, max2);
-            TypeHandle type1 = T.Range(min1, max1);
-            TypeHandle type2 = T.Range(min2, max2);
+            Type* type1 = T.Range(min1, max1);
+            Type* type2 = T.Range(min2, max2);
             CHECK(type1->Is(type2) == (min1 >= min2 && max1 <= max2));
           }
         }
@@ -914,8 +837,8 @@
       for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
         Handle<i::Object> value1 = *vt1;
         Handle<i::Object> value2 = *vt2;
-        TypeHandle const_type1 = T.Constant(value1);
-        TypeHandle const_type2 = T.Constant(value2);
+        Type* const_type1 = T.Constant(value1);
+        Type* const_type2 = T.Constant(value2);
         CHECK(const_type1->Is(const_type2) == (*value1 == *value2));
       }
     }
@@ -923,10 +846,10 @@
     // Context(T1)->Is(Context(T2)) iff T1 = T2
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle outer1 = *it1;
-        TypeHandle outer2 = *it2;
-        TypeHandle type1 = T.Context(outer1);
-        TypeHandle type2 = T.Context(outer2);
+        Type* outer1 = *it1;
+        Type* outer2 = *it2;
+        Type* type1 = T.Context(outer1);
+        Type* type2 = T.Context(outer2);
         CHECK(type1->Is(type2) == outer1->Equals(outer2));
       }
     }
@@ -934,10 +857,10 @@
     // Array(T1)->Is(Array(T2)) iff T1 = T2
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle element1 = *it1;
-        TypeHandle element2 = *it2;
-        TypeHandle type1 = T.Array1(element1);
-        TypeHandle type2 = T.Array1(element2);
+        Type* element1 = *it1;
+        Type* element2 = *it2;
+        Type* type1 = T.Array1(element1);
+        Type* type2 = T.Array1(element2);
         CHECK(type1->Is(type2) == element1->Equals(element2));
       }
     }
@@ -945,12 +868,12 @@
     // Function0(S1, T1)->Is(Function0(S2, T2)) iff S1 = S2 and T1 = T2
     for (TypeIterator i = T.types.begin(); i != T.types.end(); ++i) {
       for (TypeIterator j = T.types.begin(); j != T.types.end(); ++j) {
-        TypeHandle result1 = *i;
-        TypeHandle receiver1 = *j;
-        TypeHandle type1 = T.Function0(result1, receiver1);
-        TypeHandle result2 = T.Random();
-        TypeHandle receiver2 = T.Random();
-        TypeHandle type2 = T.Function0(result2, receiver2);
+        Type* result1 = *i;
+        Type* receiver1 = *j;
+        Type* type1 = T.Function0(result1, receiver1);
+        Type* result2 = T.Random();
+        Type* receiver2 = T.Random();
+        Type* type2 = T.Function0(result2, receiver2);
         CHECK(type1->Is(type2) ==
             (result1->Equals(result2) && receiver1->Equals(receiver2)));
       }
@@ -961,7 +884,7 @@
 
     // If IsInteger(v) then Constant(v)->Is(Range(v, v)).
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       if (type->IsConstant() && IsInteger(*type->AsConstant()->Value())) {
         CHECK(type->Is(T.Range(type->AsConstant()->Value()->Number(),
                                type->AsConstant()->Value()->Number())));
@@ -971,8 +894,8 @@
     // If Constant(x)->Is(Range(min,max)) then IsInteger(v) and min <= x <= max.
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         if (type1->IsConstant() && type2->IsRange() && type1->Is(type2)) {
           double x = type1->AsConstant()->Value()->Number();
           double min = type2->AsRange()->Min();
@@ -984,10 +907,9 @@
 
     // Lub(Range(x,y))->Is(T.Union(T.Integral32, T.OtherNumber))
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       if (type->IsRange()) {
-        TypeHandle lub = Rep::BitsetType::New(
-            Rep::BitsetType::Lub(type), T.region());
+        Type* lub = BitsetType::NewForTesting(BitsetType::Lub(type));
         CHECK(lub->Is(T.PlainNumber));
       }
     }
@@ -1068,31 +990,31 @@
   void NowIs() {
     // Least Element (Bottom): None->NowIs(T)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(T.None->NowIs(type));
     }
 
     // Greatest Element (Top): T->NowIs(Any)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(type->NowIs(T.Any));
     }
 
     // Bottom Uniqueness: T->NowIs(None) implies T = None
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       if (type->NowIs(T.None)) CheckEqual(type, T.None);
     }
 
     // Top Uniqueness: Any->NowIs(T) implies T = Any
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       if (T.Any->NowIs(type)) CheckEqual(type, T.Any);
     }
 
     // Reflexivity: T->NowIs(T)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(type->NowIs(type));
     }
 
@@ -1100,9 +1022,9 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
           CHECK(!(type1->NowIs(type2) && type2->NowIs(type3)) ||
                 type1->NowIs(type3));
         }
@@ -1112,8 +1034,8 @@
     // Antisymmetry: T1->NowIs(T2) and T2->NowIs(T1) iff T1 = T2
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         CHECK((type1->NowIs(type2) && type2->NowIs(type1)) ==
               Equal(type1, type2));
       }
@@ -1122,8 +1044,8 @@
     // T1->Is(T2) implies T1->NowIs(T2)
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         CHECK(!type1->Is(type2) || type1->NowIs(type2));
       }
     }
@@ -1133,8 +1055,8 @@
       for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
         Handle<i::Object> value1 = *vt1;
         Handle<i::Object> value2 = *vt2;
-        TypeHandle const_type1 = T.Constant(value1);
-        TypeHandle const_type2 = T.Constant(value2);
+        Type* const_type1 = T.Constant(value1);
+        Type* const_type2 = T.Constant(value2);
         CHECK(const_type1->NowIs(const_type2) == (*value1 == *value2));
       }
     }
@@ -1144,8 +1066,8 @@
       for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
         Handle<i::Map> map1 = *mt1;
         Handle<i::Map> map2 = *mt2;
-        TypeHandle class_type1 = T.Class(map1);
-        TypeHandle class_type2 = T.Class(map2);
+        Type* class_type1 = T.Class(map1);
+        Type* class_type2 = T.Class(map2);
         CHECK(class_type1->NowIs(class_type2) == (*map1 == *map2));
       }
     }
@@ -1155,8 +1077,8 @@
       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
         Handle<i::Map> map = *mt;
         Handle<i::Object> value = *vt;
-        TypeHandle const_type = T.Constant(value);
-        TypeHandle class_type = T.Class(map);
+        Type* const_type = T.Constant(value);
+        Type* class_type = T.Class(map);
         CHECK((value->IsHeapObject() &&
                i::HeapObject::cast(*value)->map() == *map)
               == const_type->NowIs(class_type));
@@ -1168,8 +1090,8 @@
       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
         Handle<i::Map> map = *mt;
         Handle<i::Object> value = *vt;
-        TypeHandle const_type = T.Constant(value);
-        TypeHandle class_type = T.Class(map);
+        Type* const_type = T.Constant(value);
+        Type* class_type = T.Class(map);
         CHECK(!class_type->NowIs(const_type));
       }
     }
@@ -1179,9 +1101,9 @@
     // T->Contains(V) iff Constant(V)->Is(T)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
-        TypeHandle type = *it;
+        Type* type = *it;
         Handle<i::Object> value = *vt;
-        TypeHandle const_type = T.Constant(value);
+        Type* const_type = T.Constant(value);
         CHECK(type->Contains(value) == const_type->Is(type));
       }
     }
@@ -1191,9 +1113,9 @@
     // T->NowContains(V) iff Constant(V)->NowIs(T)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
-        TypeHandle type = *it;
+        Type* type = *it;
         Handle<i::Object> value = *vt;
-        TypeHandle const_type = T.Constant(value);
+        Type* const_type = T.Constant(value);
         CHECK(type->NowContains(value) == const_type->NowIs(type));
       }
     }
@@ -1201,7 +1123,7 @@
     // T->Contains(V) implies T->NowContains(V)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
-        TypeHandle type = *it;
+        Type* type = *it;
         Handle<i::Object> value = *vt;
         CHECK(!type->Contains(value) || type->NowContains(value));
       }
@@ -1210,9 +1132,9 @@
     // NowOf(V)->Is(T) implies T->NowContains(V)
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
-        TypeHandle type = *it;
+        Type* type = *it;
         Handle<i::Object> value = *vt;
-        TypeHandle nowof_type = T.Of(value);
+        Type* nowof_type = T.Of(value);
         CHECK(!nowof_type->NowIs(type) || type->NowContains(value));
       }
     }
@@ -1221,27 +1143,27 @@
   void Maybe() {
     // T->Maybe(Any) iff T inhabited
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(type->Maybe(T.Any) == type->IsInhabited());
     }
 
     // T->Maybe(None) never
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(!type->Maybe(T.None));
     }
 
     // Reflexivity upto Inhabitation: T->Maybe(T) iff T inhabited
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
+      Type* type = *it;
       CHECK(type->Maybe(type) == type->IsInhabited());
     }
 
     // Symmetry: T1->Maybe(T2) iff T2->Maybe(T1)
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         CHECK(type1->Maybe(type2) == type2->Maybe(type1));
       }
     }
@@ -1249,8 +1171,8 @@
     // T1->Maybe(T2) implies T1, T2 inhabited
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         CHECK(!type1->Maybe(type2) ||
               (type1->IsInhabited() && type2->IsInhabited()));
       }
@@ -1259,9 +1181,9 @@
     // T1->Maybe(T2) implies Intersect(T1, T2) inhabited
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle intersect12 = T.Intersect(type1, type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* intersect12 = T.Intersect(type1, type2);
         CHECK(!type1->Maybe(type2) || intersect12->IsInhabited());
       }
     }
@@ -1269,8 +1191,8 @@
     // T1->Is(T2) and T1 inhabited implies T1->Maybe(T2)
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         CHECK(!(type1->Is(type2) && type1->IsInhabited()) ||
               type1->Maybe(type2));
       }
@@ -1281,8 +1203,8 @@
       for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
         Handle<i::Object> value1 = *vt1;
         Handle<i::Object> value2 = *vt2;
-        TypeHandle const_type1 = T.Constant(value1);
-        TypeHandle const_type2 = T.Constant(value2);
+        Type* const_type1 = T.Constant(value1);
+        Type* const_type2 = T.Constant(value2);
         CHECK(const_type1->Maybe(const_type2) == (*value1 == *value2));
       }
     }
@@ -1292,8 +1214,8 @@
       for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
         Handle<i::Map> map1 = *mt1;
         Handle<i::Map> map2 = *mt2;
-        TypeHandle class_type1 = T.Class(map1);
-        TypeHandle class_type2 = T.Class(map2);
+        Type* class_type1 = T.Class(map1);
+        Type* class_type2 = T.Class(map2);
         CHECK(class_type1->Maybe(class_type2) == (*map1 == *map2));
       }
     }
@@ -1305,8 +1227,8 @@
       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
         Handle<i::Map> map = *mt;
         Handle<i::Object> value = *vt;
-        TypeHandle const_type = T.Constant(value);
-        TypeHandle class_type = T.Class(map);
+        Type* const_type = T.Constant(value);
+        Type* class_type = T.Class(map);
         CHECK(!const_type->Maybe(class_type));
       }
     }
@@ -1319,8 +1241,8 @@
       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
         Handle<i::Map> map = *mt;
         Handle<i::Object> value = *vt;
-        TypeHandle const_type = T.Constant(value);
-        TypeHandle class_type = T.Class(map);
+        Type* const_type = T.Constant(value);
+        Type* class_type = T.Class(map);
         CHECK(!class_type->Maybe(const_type));
       }
     }
@@ -1383,32 +1305,32 @@
   void Union1() {
     // Identity: Union(T, None) = T
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
-      TypeHandle union_type = T.Union(type, T.None);
+      Type* type = *it;
+      Type* union_type = T.Union(type, T.None);
       CheckEqual(union_type, type);
     }
 
     // Domination: Union(T, Any) = Any
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
-      TypeHandle union_type = T.Union(type, T.Any);
+      Type* type = *it;
+      Type* union_type = T.Union(type, T.Any);
       CheckEqual(union_type, T.Any);
     }
 
     // Idempotence: Union(T, T) = T
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
-      TypeHandle union_type = T.Union(type, type);
+      Type* type = *it;
+      Type* union_type = T.Union(type, type);
       CheckEqual(union_type, type);
     }
 
     // Commutativity: Union(T1, T2) = Union(T2, T1)
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle union12 = T.Union(type1, type2);
-        TypeHandle union21 = T.Union(type2, type1);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* union12 = T.Union(type1, type2);
+        Type* union21 = T.Union(type2, type1);
         CheckEqual(union12, union21);
       }
     }
@@ -1421,13 +1343,13 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle union12 = T.Union(type1, type2);
-          TypeHandle union23 = T.Union(type2, type3);
-          TypeHandle union1_23 = T.Union(type1, union23);
-          TypeHandle union12_3 = T.Union(union12, type3);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* union12 = T.Union(type1, type2);
+          Type* union23 = T.Union(type2, type3);
+          Type* union1_23 = T.Union(type1, union23);
+          Type* union12_3 = T.Union(union12, type3);
           CheckEqual(union1_23, union12_3);
         }
       }
@@ -1437,9 +1359,9 @@
     // Meet: T1->Is(Union(T1, T2)) and T2->Is(Union(T1, T2))
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle union12 = T.Union(type1, type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* union12 = T.Union(type1, type2);
         CHECK(type1->Is(union12));
         CHECK(type2->Is(union12));
       }
@@ -1448,9 +1370,9 @@
     // Upper Boundedness: T1->Is(T2) implies Union(T1, T2) = T2
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle union12 = T.Union(type1, type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* union12 = T.Union(type1, type2);
         if (type1->Is(type2)) CheckEqual(union12, type2);
       }
     }
@@ -1463,11 +1385,11 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle union13 = T.Union(type1, type3);
-          TypeHandle union23 = T.Union(type2, type3);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* union13 = T.Union(type1, type3);
+          Type* union23 = T.Union(type2, type3);
           CHECK(!type1->Is(type2) || union13->Is(union23));
         }
       }
@@ -1485,10 +1407,10 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle union12 = T.Union(type1, type2);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* union12 = T.Union(type1, type2);
           CHECK(!(type1->Is(type3) && type2->Is(type3)) || union12->Is(type3));
         }
       }
@@ -1502,10 +1424,10 @@
       HandleScope scope(isolate);
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = it2; it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle union23 = T.Union(type2, type3);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* union23 = T.Union(type2, type3);
           CHECK(!(type1->Is(type2) || type1->Is(type3)) || type1->Is(union23));
         }
       }
@@ -1628,32 +1550,32 @@
   void Intersect() {
     // Identity: Intersect(T, Any) = T
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
-      TypeHandle intersect_type = T.Intersect(type, T.Any);
+      Type* type = *it;
+      Type* intersect_type = T.Intersect(type, T.Any);
       CheckEqual(intersect_type, type);
     }
 
     // Domination: Intersect(T, None) = None
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
-      TypeHandle intersect_type = T.Intersect(type, T.None);
+      Type* type = *it;
+      Type* intersect_type = T.Intersect(type, T.None);
       CheckEqual(intersect_type, T.None);
     }
 
     // Idempotence: Intersect(T, T) = T
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type = *it;
-      TypeHandle intersect_type = T.Intersect(type, type);
+      Type* type = *it;
+      Type* intersect_type = T.Intersect(type, type);
       CheckEqual(intersect_type, type);
     }
 
     // Commutativity: Intersect(T1, T2) = Intersect(T2, T1)
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle intersect12 = T.Intersect(type1, type2);
-        TypeHandle intersect21 = T.Intersect(type2, type1);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* intersect12 = T.Intersect(type1, type2);
+        Type* intersect21 = T.Intersect(type2, type1);
         CheckEqual(intersect12, intersect21);
       }
     }
@@ -1669,13 +1591,13 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle intersect12 = T.Intersect(type1, type2);
-          TypeHandle intersect23 = T.Intersect(type2, type3);
-          TypeHandle intersect1_23 = T.Intersect(type1, intersect23);
-          TypeHandle intersect12_3 = T.Intersect(intersect12, type3);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* intersect12 = T.Intersect(type1, type2);
+          Type* intersect23 = T.Intersect(type2, type3);
+          Type* intersect1_23 = T.Intersect(type1, intersect23);
+          Type* intersect12_3 = T.Intersect(intersect12, type3);
           CheckEqual(intersect1_23, intersect12_3);
         }
       }
@@ -1691,9 +1613,9 @@
     /*
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle intersect12 = T.Intersect(type1, type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* intersect12 = T.Intersect(type1, type2);
         CHECK(intersect12->Is(type1));
         CHECK(intersect12->Is(type2));
       }
@@ -1703,9 +1625,9 @@
     // Lower Boundedness: T1->Is(T2) implies Intersect(T1, T2) = T1
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        TypeHandle intersect12 = T.Intersect(type1, type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        Type* intersect12 = T.Intersect(type1, type2);
         if (type1->Is(type2)) CheckEqual(intersect12, type1);
       }
     }
@@ -1719,11 +1641,11 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle intersect13 = T.Intersect(type1, type3);
-          TypeHandle intersect23 = T.Intersect(type2, type3);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* intersect13 = T.Intersect(type1, type3);
+          Type* intersect23 = T.Intersect(type2, type3);
           CHECK(!type1->Is(type2) || intersect13->Is(intersect23));
         }
       }
@@ -1739,10 +1661,10 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle intersect12 = T.Intersect(type1, type2);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* intersect12 = T.Intersect(type1, type2);
           CHECK(!(type1->Is(type3) || type2->Is(type3)) ||
                 intersect12->Is(type3));
         }
@@ -1755,10 +1677,10 @@
       HandleScope scope(isolate);
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle intersect23 = T.Intersect(type2, type3);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* intersect23 = T.Intersect(type2, type3);
           CHECK(!(type1->Is(type2) && type1->Is(type3)) ||
                 type1->Is(intersect23));
         }
@@ -1871,14 +1793,14 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle union12 = T.Union(type1, type2);
-          TypeHandle union13 = T.Union(type1, type3);
-          TypeHandle intersect23 = T.Intersect(type2, type3);
-          TypeHandle union1_23 = T.Union(type1, intersect23);
-          TypeHandle intersect12_13 = T.Intersect(union12, union13);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* union12 = T.Union(type1, type2);
+          Type* union13 = T.Union(type1, type3);
+          Type* intersect23 = T.Intersect(type2, type3);
+          Type* union1_23 = T.Union(type1, intersect23);
+          Type* intersect12_13 = T.Intersect(union12, union13);
           CHECK(Equal(union1_23, intersect12_13));
         }
       }
@@ -1894,14 +1816,14 @@
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
-          TypeHandle type1 = *it1;
-          TypeHandle type2 = *it2;
-          TypeHandle type3 = *it3;
-          TypeHandle intersect12 = T.Intersect(type1, type2);
-          TypeHandle intersect13 = T.Intersect(type1, type3);
-          TypeHandle union23 = T.Union(type2, type3);
-          TypeHandle intersect1_23 = T.Intersect(type1, union23);
-          TypeHandle union12_13 = T.Union(intersect12, intersect13);
+          Type* type1 = *it1;
+          Type* type2 = *it2;
+          Type* type3 = *it3;
+          Type* intersect12 = T.Intersect(type1, type2);
+          Type* intersect13 = T.Intersect(type1, type3);
+          Type* union23 = T.Union(type2, type3);
+          Type* intersect1_23 = T.Intersect(type1, union23);
+          Type* union12_13 = T.Union(intersect12, intersect13);
           CHECK(Equal(intersect1_23, union12_13));
         }
       }
@@ -1912,9 +1834,9 @@
   void GetRange() {
     // GetRange(Range(a, b)) = Range(a, b).
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
-      TypeHandle type1 = *it1;
+      Type* type1 = *it1;
       if (type1->IsRange()) {
-        typename Type::RangeType* range = type1->GetRange();
+        RangeType* range = type1->GetRange()->AsRange();
         CHECK(type1->Min() == range->Min());
         CHECK(type1->Max() == range->Max());
       }
@@ -1923,10 +1845,10 @@
     // GetRange(Union(Constant(x), Range(min,max))) == Range(min, max).
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
+        Type* type1 = *it1;
+        Type* type2 = *it2;
         if (type1->IsConstant() && type2->IsRange()) {
-          TypeHandle u = T.Union(type1, type2);
+          Type* u = T.Union(type1, type2);
 
           CHECK(type2->Min() == u->GetRange()->Min());
           CHECK(type2->Max() == u->GetRange()->Max());
@@ -1935,201 +1857,69 @@
     }
   }
 
-  template<class Type2, class TypeHandle2, class Region2, class Rep2>
-  void Convert() {
-    Types<Type2, TypeHandle2, Region2> T2(Rep2::ToRegion(&zone, isolate),
-                                          isolate,
-                                          isolate->random_number_generator());
-    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
-      TypeHandle type1 = *it;
-      TypeHandle2 type2 = T2.template Convert<Type>(type1);
-      TypeHandle type3 = T.template Convert<Type2>(type2);
-      CheckEqual(type1, type3);
-    }
-  }
-
   void HTypeFromType() {
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
-        TypeHandle type1 = *it1;
-        TypeHandle type2 = *it2;
-        HType htype1 = HType::FromType<Type>(type1);
-        HType htype2 = HType::FromType<Type>(type2);
+        Type* type1 = *it1;
+        Type* type2 = *it2;
+        HType htype1 = HType::FromType(type1);
+        HType htype2 = HType::FromType(type2);
         CHECK(!type1->Is(type2) || htype1.IsSubtypeOf(htype2));
       }
     }
   }
 };
 
-typedef Tests<Type, Type*, Zone, ZoneRep> ZoneTests;
-typedef Tests<HeapType, Handle<HeapType>, Isolate, HeapRep> HeapTests;
+TEST(IsSomeType_zone) { Tests().IsSomeType(); }
 
+TEST(PointwiseRepresentation_zone) { Tests().PointwiseRepresentation(); }
 
-TEST(IsSomeType_zone) { ZoneTests().IsSomeType(); }
+TEST(BitsetType_zone) { Tests().Bitset(); }
 
+TEST(ClassType_zone) { Tests().Class(); }
 
-TEST(IsSomeType_heap) { HeapTests().IsSomeType(); }
+TEST(ConstantType_zone) { Tests().Constant(); }
 
+TEST(RangeType_zone) { Tests().Range(); }
 
-TEST(PointwiseRepresentation_zone) { ZoneTests().PointwiseRepresentation(); }
+TEST(ArrayType_zone) { Tests().Array(); }
 
+TEST(FunctionType_zone) { Tests().Function(); }
 
-TEST(PointwiseRepresentation_heap) { HeapTests().PointwiseRepresentation(); }
+TEST(Of_zone) { Tests().Of(); }
 
+TEST(NowOf_zone) { Tests().NowOf(); }
 
-TEST(BitsetType_zone) { ZoneTests().Bitset(); }
+TEST(MinMax_zone) { Tests().MinMax(); }
 
+TEST(BitsetGlb_zone) { Tests().BitsetGlb(); }
 
-TEST(BitsetType_heap) { HeapTests().Bitset(); }
+TEST(BitsetLub_zone) { Tests().BitsetLub(); }
 
+TEST(Is1_zone) { Tests().Is1(); }
 
-TEST(ClassType_zone) { ZoneTests().Class(); }
+TEST(Is2_zone) { Tests().Is2(); }
 
+TEST(NowIs_zone) { Tests().NowIs(); }
 
-TEST(ClassType_heap) { HeapTests().Class(); }
+TEST(Contains_zone) { Tests().Contains(); }
 
+TEST(NowContains_zone) { Tests().NowContains(); }
 
-TEST(ConstantType_zone) { ZoneTests().Constant(); }
+TEST(Maybe_zone) { Tests().Maybe(); }
 
+TEST(Union1_zone) { Tests().Union1(); }
 
-TEST(ConstantType_heap) { HeapTests().Constant(); }
+TEST(Union2_zone) { Tests().Union2(); }
 
+TEST(Union3_zone) { Tests().Union3(); }
 
-TEST(RangeType_zone) { ZoneTests().Range(); }
+TEST(Union4_zone) { Tests().Union4(); }
 
+TEST(Intersect_zone) { Tests().Intersect(); }
 
-TEST(RangeType_heap) { HeapTests().Range(); }
+TEST(Distributivity_zone) { Tests().Distributivity(); }
 
+TEST(GetRange_zone) { Tests().GetRange(); }
 
-TEST(ArrayType_zone) { ZoneTests().Array(); }
-
-
-TEST(ArrayType_heap) { HeapTests().Array(); }
-
-
-TEST(FunctionType_zone) { ZoneTests().Function(); }
-
-
-TEST(FunctionType_heap) { HeapTests().Function(); }
-
-
-TEST(Of_zone) { ZoneTests().Of(); }
-
-
-TEST(Of_heap) { HeapTests().Of(); }
-
-
-TEST(NowOf_zone) { ZoneTests().NowOf(); }
-
-
-TEST(NowOf_heap) { HeapTests().NowOf(); }
-
-
-TEST(MinMax_zone) { ZoneTests().MinMax(); }
-
-
-TEST(MinMax_heap) { HeapTests().MinMax(); }
-
-
-TEST(BitsetGlb_zone) { ZoneTests().BitsetGlb(); }
-
-
-TEST(BitsetGlb_heap) { HeapTests().BitsetGlb(); }
-
-
-TEST(BitsetLub_zone) { ZoneTests().BitsetLub(); }
-
-
-TEST(BitsetLub_heap) { HeapTests().BitsetLub(); }
-
-
-TEST(Is1_zone) { ZoneTests().Is1(); }
-
-
-TEST(Is1_heap) { HeapTests().Is1(); }
-
-
-TEST(Is2_zone) { ZoneTests().Is2(); }
-
-
-TEST(Is2_heap) { HeapTests().Is2(); }
-
-
-TEST(NowIs_zone) { ZoneTests().NowIs(); }
-
-
-TEST(NowIs_heap) { HeapTests().NowIs(); }
-
-
-TEST(Contains_zone) { ZoneTests().Contains(); }
-
-
-TEST(Contains_heap) { HeapTests().Contains(); }
-
-
-TEST(NowContains_zone) { ZoneTests().NowContains(); }
-
-
-TEST(NowContains_heap) { HeapTests().NowContains(); }
-
-
-TEST(Maybe_zone) { ZoneTests().Maybe(); }
-
-
-TEST(Maybe_heap) { HeapTests().Maybe(); }
-
-
-TEST(Union1_zone) { ZoneTests().Union1(); }
-
-
-TEST(Union1_heap) { HeapTests().Union1(); }
-
-
-TEST(Union2_zone) { ZoneTests().Union2(); }
-
-
-TEST(Union2_heap) { HeapTests().Union2(); }
-
-
-TEST(Union3_zone) { ZoneTests().Union3(); }
-
-
-TEST(Union3_heap) { HeapTests().Union3(); }
-
-
-TEST(Union4_zone) { ZoneTests().Union4(); }
-
-
-TEST(Union4_heap) { HeapTests().Union4(); }
-
-
-TEST(Intersect_zone) { ZoneTests().Intersect(); }
-
-
-TEST(Intersect_heap) { HeapTests().Intersect(); }
-
-
-TEST(Distributivity_zone) { ZoneTests().Distributivity(); }
-
-
-TEST(Distributivity_heap) { HeapTests().Distributivity(); }
-
-
-TEST(GetRange_zone) { ZoneTests().GetRange(); }
-
-
-TEST(GetRange_heap) { HeapTests().GetRange(); }
-
-
-TEST(Convert_zone) {
-  ZoneTests().Convert<HeapType, Handle<HeapType>, Isolate, HeapRep>();
-}
-
-
-TEST(Convert_heap) { HeapTests().Convert<Type, Type*, Zone, ZoneRep>(); }
-
-
-TEST(HTypeFromType_zone) { ZoneTests().HTypeFromType(); }
-
-
-TEST(HTypeFromType_heap) { HeapTests().HTypeFromType(); }
+TEST(HTypeFromType_zone) { Tests().HTypeFromType(); }
diff --git a/test/cctest/test-unboxed-doubles.cc b/test/cctest/test-unboxed-doubles.cc
index 3906d84..f195a31 100644
--- a/test/cctest/test-unboxed-doubles.cc
+++ b/test/cctest/test-unboxed-doubles.cc
@@ -10,6 +10,7 @@
 #include "src/compilation-cache.h"
 #include "src/execution.h"
 #include "src/factory.h"
+#include "src/field-type.h"
 #include "src/global-handles.h"
 #include "src/heap/slots-buffer.h"
 #include "src/ic/ic.h"
@@ -947,7 +948,7 @@
   const int kSplitFieldIndex = 32;
   const int kTrimmedLayoutDescriptorLength = 64;
 
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
   Handle<Map> map = Map::Create(isolate, kFieldCount);
   for (int i = 0; i < kSplitFieldIndex; i++) {
     map = Map::CopyWithField(map, MakeName("prop", i), any_type, NONE,
@@ -1035,7 +1036,7 @@
   // a pointer to "from space" pointer. Do scavenge one more time and ensure
   // that it didn't crash or corrupt the double value stored in the object.
 
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
   Handle<Map> map = Map::Create(isolate, 10);
   map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE,
                            Representation::Double(),
@@ -1060,7 +1061,7 @@
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
 
   // Create temp object in the new space.
-  Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS);
+  Handle<JSArray> temp = factory->NewJSArray(0, FAST_ELEMENTS);
   CHECK(isolate->heap()->new_space()->Contains(*temp));
 
   // Construct a double value that looks like a pointer to the new space object
@@ -1097,7 +1098,7 @@
   // scavenges to promote |obj| to old space, a GC in old space and ensure that
   // the tagged value was properly updated after candidates evacuation.
 
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
   Handle<Map> map = Map::Create(isolate, 10);
   map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE,
                            Representation::Double(),
@@ -1321,7 +1322,7 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
   Isolate* isolate = CcTest::i_isolate();
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   Handle<Map> split_map;
   {
@@ -1363,65 +1364,6 @@
 }
 
 
-TEST(StoreBufferScanOnScavenge) {
-  CcTest::InitializeVM();
-  Isolate* isolate = CcTest::i_isolate();
-  Factory* factory = isolate->factory();
-  v8::HandleScope scope(CcTest::isolate());
-
-  Handle<HeapType> any_type = HeapType::Any(isolate);
-  Handle<Map> map = Map::Create(isolate, 10);
-  map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE,
-                           Representation::Double(),
-                           INSERT_TRANSITION).ToHandleChecked();
-
-  // Create object in new space.
-  Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED);
-
-  Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5);
-  obj->WriteToField(0, *heap_number);
-
-  {
-    // Ensure the object is properly set up.
-    DescriptorArray* descriptors = map->instance_descriptors();
-    CHECK(descriptors->GetDetails(0).representation().IsDouble());
-    FieldIndex field_index = FieldIndex::ForDescriptor(*map, 0);
-    CHECK(field_index.is_inobject() && field_index.is_double());
-    CHECK_EQ(FLAG_unbox_double_fields, map->IsUnboxedDoubleField(field_index));
-    CHECK_EQ(42.5, GetDoubleFieldValue(*obj, field_index));
-  }
-  CHECK(isolate->heap()->new_space()->Contains(*obj));
-
-  // Trigger GCs so that the newly allocated object moves to old gen.
-  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
-  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
-
-  CHECK(isolate->heap()->old_space()->Contains(*obj));
-
-  // Create temp object in the new space.
-  Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS);
-  CHECK(isolate->heap()->new_space()->Contains(*temp));
-
-  // Construct a double value that looks like a pointer to the new space object
-  // and store it into the obj.
-  Address fake_object = reinterpret_cast<Address>(*temp) + kPointerSize;
-  double boom_value = bit_cast<double>(fake_object);
-
-  FieldIndex field_index = FieldIndex::ForDescriptor(obj->map(), 0);
-  Handle<HeapNumber> boom_number = factory->NewHeapNumber(boom_value, MUTABLE);
-  obj->FastPropertyAtPut(field_index, *boom_number);
-
-  // Enforce scan on scavenge for the obj's page.
-  MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
-  chunk->set_scan_on_scavenge(true);
-
-  // Trigger GCs and force evacuation. Should not crash there.
-  CcTest::heap()->CollectAllGarbage();
-
-  CHECK_EQ(boom_value, GetDoubleFieldValue(*obj, field_index));
-}
-
-
 static void TestWriteBarrier(Handle<Map> map, Handle<Map> new_map,
                              int tagged_descriptor, int double_descriptor,
                              bool check_tagged_value = true) {
@@ -1580,7 +1522,7 @@
   Isolate* isolate = CcTest::i_isolate();
   v8::HandleScope scope(CcTest::isolate());
 
-  Handle<HeapType> any_type = HeapType::Any(isolate);
+  Handle<FieldType> any_type = FieldType::Any(isolate);
 
   CompileRun("function func() { return 1; }");
 
@@ -1608,9 +1550,7 @@
   }
 }
 
-
-// TODO(ishell): enable when this issue is fixed.
-DISABLED_TEST(WriteBarrierObjectShiftFieldsRight) {
+TEST(WriteBarrierObjectShiftFieldsRight) {
   TestWriteBarrierObjectShiftFieldsRight(OLD_TO_NEW_WRITE_BARRIER);
 }
 
diff --git a/test/cctest/test-weakmaps.cc b/test/cctest/test-weakmaps.cc
index 2630110..781ad1f 100644
--- a/test/cctest/test-weakmaps.cc
+++ b/test/cctest/test-weakmaps.cc
@@ -193,7 +193,7 @@
     HandleScope scope(isolate);
     for (int i = 0; i < 32; i++) {
       Handle<JSObject> object = factory->NewJSObject(function, TENURED);
-      CHECK(!heap->InNewSpace(object->address()));
+      CHECK(!heap->InNewSpace(*object));
       CHECK(!first_page->Contains(object->address()));
       int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
       JSWeakCollection::Set(weakmap, key, object, hash);
@@ -231,7 +231,7 @@
   Handle<JSObject> keys[32];
   for (int i = 0; i < 32; i++) {
     keys[i] = factory->NewJSObject(function, TENURED);
-    CHECK(!heap->InNewSpace(keys[i]->address()));
+    CHECK(!heap->InNewSpace(*keys[i]));
     CHECK(!first_page->Contains(keys[i]->address()));
   }
   Handle<JSWeakMap> weakmap = AllocateJSWeakMap(isolate);
diff --git a/test/cctest/test-weaksets.cc b/test/cctest/test-weaksets.cc
index 6998e0f..643bb48 100644
--- a/test/cctest/test-weaksets.cc
+++ b/test/cctest/test-weaksets.cc
@@ -192,7 +192,7 @@
     HandleScope scope(isolate);
     for (int i = 0; i < 32; i++) {
       Handle<JSObject> object = factory->NewJSObject(function, TENURED);
-      CHECK(!heap->InNewSpace(object->address()));
+      CHECK(!heap->InNewSpace(*object));
       CHECK(!first_page->Contains(object->address()));
       int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
       JSWeakCollection::Set(weakset, key, object, hash);
@@ -230,7 +230,7 @@
   Handle<JSObject> keys[32];
   for (int i = 0; i < 32; i++) {
     keys[i] = factory->NewJSObject(function, TENURED);
-    CHECK(!heap->InNewSpace(keys[i]->address()));
+    CHECK(!heap->InNewSpace(*keys[i]));
     CHECK(!first_page->Contains(keys[i]->address()));
   }
   Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
diff --git a/test/cctest/trace-extension.cc b/test/cctest/trace-extension.cc
index ea2b2ce..77a29e9 100644
--- a/test/cctest/trace-extension.cc
+++ b/test/cctest/trace-extension.cc
@@ -108,7 +108,7 @@
   regs.sp =
       reinterpret_cast<Address>(trace_env.sample) - 10240;
   trace_env.sample->Init(CcTest::i_isolate(), regs,
-                         TickSample::kSkipCEntryFrame);
+                         TickSample::kSkipCEntryFrame, true);
 }
 
 
diff --git a/test/cctest/types-fuzz.h b/test/cctest/types-fuzz.h
index 5c43e8e..79e4608 100644
--- a/test/cctest/types-fuzz.h
+++ b/test/cctest/types-fuzz.h
@@ -35,19 +35,18 @@
 namespace internal {
 
 
-template<class Type, class TypeHandle, class Region>
 class Types {
  public:
-  Types(Region* region, Isolate* isolate, v8::base::RandomNumberGenerator* rng)
-      : region_(region), isolate_(isolate), rng_(rng) {
-    #define DECLARE_TYPE(name, value) \
-      name = Type::name(region);      \
-      types.push_back(name);
+  Types(Zone* zone, Isolate* isolate, v8::base::RandomNumberGenerator* rng)
+      : zone_(zone), isolate_(isolate), rng_(rng) {
+#define DECLARE_TYPE(name, value) \
+  name = Type::name();            \
+  types.push_back(name);
     PROPER_BITSET_TYPE_LIST(DECLARE_TYPE)
     #undef DECLARE_TYPE
 
-    SignedSmall = Type::SignedSmall(region);
-    UnsignedSmall = Type::UnsignedSmall(region);
+    SignedSmall = Type::SignedSmall();
+    UnsignedSmall = Type::UnsignedSmall();
 
     object_map = isolate->factory()->NewMap(
         JS_OBJECT_TYPE, JSObject::kHeaderSize);
@@ -56,16 +55,16 @@
     number_map = isolate->factory()->NewMap(
         HEAP_NUMBER_TYPE, HeapNumber::kSize);
     uninitialized_map = isolate->factory()->uninitialized_map();
-    ObjectClass = Type::Class(object_map, region);
-    ArrayClass = Type::Class(array_map, region);
-    NumberClass = Type::Class(number_map, region);
-    UninitializedClass = Type::Class(uninitialized_map, region);
+    ObjectClass = Type::Class(object_map, zone);
+    ArrayClass = Type::Class(array_map, zone);
+    NumberClass = Type::Class(number_map, zone);
+    UninitializedClass = Type::Class(uninitialized_map, zone);
 
     maps.push_back(object_map);
     maps.push_back(array_map);
     maps.push_back(uninitialized_map);
     for (MapVector::iterator it = maps.begin(); it != maps.end(); ++it) {
-      types.push_back(Type::Class(*it, region));
+      types.push_back(Type::Class(*it, zone));
     }
 
     smi = handle(Smi::FromInt(666), isolate);
@@ -74,13 +73,13 @@
     object2 = isolate->factory()->NewJSObjectFromMap(object_map);
     array = isolate->factory()->NewJSArray(20);
     uninitialized = isolate->factory()->uninitialized_value();
-    SmiConstant = Type::Constant(smi, region);
-    Signed32Constant = Type::Constant(signed32, region);
+    SmiConstant = Type::Constant(smi, zone);
+    Signed32Constant = Type::Constant(signed32, zone);
 
-    ObjectConstant1 = Type::Constant(object1, region);
-    ObjectConstant2 = Type::Constant(object2, region);
-    ArrayConstant = Type::Constant(array, region);
-    UninitializedConstant = Type::Constant(uninitialized, region);
+    ObjectConstant1 = Type::Constant(object1, zone);
+    ObjectConstant2 = Type::Constant(object2, zone);
+    ArrayConstant = Type::Constant(array, zone);
+    UninitializedConstant = Type::Constant(uninitialized, zone);
 
     values.push_back(smi);
     values.push_back(signed32);
@@ -89,7 +88,7 @@
     values.push_back(array);
     values.push_back(uninitialized);
     for (ValueVector::iterator it = values.begin(); it != values.end(); ++it) {
-      types.push_back(Type::Constant(*it, region));
+      types.push_back(Type::Constant(*it, zone));
     }
 
     integers.push_back(isolate->factory()->NewNumber(-V8_INFINITY));
@@ -103,16 +102,16 @@
       if (!IsMinusZero(x)) integers.push_back(isolate->factory()->NewNumber(x));
     }
 
-    Integer = Type::Range(-V8_INFINITY, +V8_INFINITY, region);
+    Integer = Type::Range(-V8_INFINITY, +V8_INFINITY, zone);
 
-    NumberArray = Type::Array(Number, region);
-    StringArray = Type::Array(String, region);
-    AnyArray = Type::Array(Any, region);
+    NumberArray = Type::Array(Number, zone);
+    StringArray = Type::Array(String, zone);
+    AnyArray = Type::Array(Any, zone);
 
-    SignedFunction1 = Type::Function(SignedSmall, SignedSmall, region);
-    NumberFunction1 = Type::Function(Number, Number, region);
-    NumberFunction2 = Type::Function(Number, Number, Number, region);
-    MethodFunction = Type::Function(String, Object, 0, region);
+    SignedFunction1 = Type::Function(SignedSmall, SignedSmall, zone);
+    NumberFunction1 = Type::Function(Number, Number, zone);
+    NumberFunction2 = Type::Function(Number, Number, Number, zone);
+    MethodFunction = Type::Function(String, Object, 0, zone);
 
     for (int i = 0; i < 30; ++i) {
       types.push_back(Fuzz());
@@ -131,40 +130,40 @@
   Handle<i::JSArray> array;
   Handle<i::Oddball> uninitialized;
 
-  #define DECLARE_TYPE(name, value) TypeHandle name;
+#define DECLARE_TYPE(name, value) Type* name;
   PROPER_BITSET_TYPE_LIST(DECLARE_TYPE)
   #undef DECLARE_TYPE
 
-#define DECLARE_TYPE(name, value) TypeHandle Mask##name##ForTesting;
+#define DECLARE_TYPE(name, value) Type* Mask##name##ForTesting;
   MASK_BITSET_TYPE_LIST(DECLARE_TYPE)
 #undef DECLARE_TYPE
-  TypeHandle SignedSmall;
-  TypeHandle UnsignedSmall;
+  Type* SignedSmall;
+  Type* UnsignedSmall;
 
-  TypeHandle ObjectClass;
-  TypeHandle ArrayClass;
-  TypeHandle NumberClass;
-  TypeHandle UninitializedClass;
+  Type* ObjectClass;
+  Type* ArrayClass;
+  Type* NumberClass;
+  Type* UninitializedClass;
 
-  TypeHandle SmiConstant;
-  TypeHandle Signed32Constant;
-  TypeHandle ObjectConstant1;
-  TypeHandle ObjectConstant2;
-  TypeHandle ArrayConstant;
-  TypeHandle UninitializedConstant;
+  Type* SmiConstant;
+  Type* Signed32Constant;
+  Type* ObjectConstant1;
+  Type* ObjectConstant2;
+  Type* ArrayConstant;
+  Type* UninitializedConstant;
 
-  TypeHandle Integer;
+  Type* Integer;
 
-  TypeHandle NumberArray;
-  TypeHandle StringArray;
-  TypeHandle AnyArray;
+  Type* NumberArray;
+  Type* StringArray;
+  Type* AnyArray;
 
-  TypeHandle SignedFunction1;
-  TypeHandle NumberFunction1;
-  TypeHandle NumberFunction2;
-  TypeHandle MethodFunction;
+  Type* SignedFunction1;
+  Type* NumberFunction1;
+  Type* NumberFunction2;
+  Type* MethodFunction;
 
-  typedef std::vector<TypeHandle> TypeVector;
+  typedef std::vector<Type*> TypeVector;
   typedef std::vector<Handle<i::Map> > MapVector;
   typedef std::vector<Handle<i::Object> > ValueVector;
 
@@ -173,94 +172,70 @@
   ValueVector values;
   ValueVector integers;  // "Integer" values used for range limits.
 
-  TypeHandle Of(Handle<i::Object> value) {
-    return Type::Of(value, region_);
+  Type* Of(Handle<i::Object> value) { return Type::Of(value, zone_); }
+
+  Type* NowOf(Handle<i::Object> value) { return Type::NowOf(value, zone_); }
+
+  Type* Class(Handle<i::Map> map) { return Type::Class(map, zone_); }
+
+  Type* Constant(Handle<i::Object> value) {
+    return Type::Constant(value, zone_);
   }
 
-  TypeHandle NowOf(Handle<i::Object> value) {
-    return Type::NowOf(value, region_);
+  Type* Range(double min, double max) { return Type::Range(min, max, zone_); }
+
+  Type* Context(Type* outer) { return Type::Context(outer, zone_); }
+
+  Type* Array1(Type* element) { return Type::Array(element, zone_); }
+
+  Type* Function0(Type* result, Type* receiver) {
+    return Type::Function(result, receiver, 0, zone_);
   }
 
-  TypeHandle Class(Handle<i::Map> map) {
-    return Type::Class(map, region_);
-  }
-
-  TypeHandle Constant(Handle<i::Object> value) {
-    return Type::Constant(value, region_);
-  }
-
-  TypeHandle Range(double min, double max) {
-    return Type::Range(min, max, region_);
-  }
-
-  TypeHandle Context(TypeHandle outer) {
-    return Type::Context(outer, region_);
-  }
-
-  TypeHandle Array1(TypeHandle element) {
-    return Type::Array(element, region_);
-  }
-
-  TypeHandle Function0(TypeHandle result, TypeHandle receiver) {
-    return Type::Function(result, receiver, 0, region_);
-  }
-
-  TypeHandle Function1(TypeHandle result, TypeHandle receiver, TypeHandle arg) {
-    TypeHandle type = Type::Function(result, receiver, 1, region_);
+  Type* Function1(Type* result, Type* receiver, Type* arg) {
+    Type* type = Type::Function(result, receiver, 1, zone_);
     type->AsFunction()->InitParameter(0, arg);
     return type;
   }
 
-  TypeHandle Function2(TypeHandle result, TypeHandle arg1, TypeHandle arg2) {
-    return Type::Function(result, arg1, arg2, region_);
+  Type* Function2(Type* result, Type* arg1, Type* arg2) {
+    return Type::Function(result, arg1, arg2, zone_);
   }
 
-  TypeHandle Union(TypeHandle t1, TypeHandle t2) {
-    return Type::Union(t1, t2, region_);
-  }
+  Type* Union(Type* t1, Type* t2) { return Type::Union(t1, t2, zone_); }
 
-  TypeHandle Intersect(TypeHandle t1, TypeHandle t2) {
-    return Type::Intersect(t1, t2, region_);
-  }
+  Type* Intersect(Type* t1, Type* t2) { return Type::Intersect(t1, t2, zone_); }
 
-  TypeHandle Representation(TypeHandle t) {
-    return Type::Representation(t, region_);
-  }
+  Type* Representation(Type* t) { return Type::Representation(t, zone_); }
 
-  // TypeHandle Semantic(TypeHandle t) { return Intersect(t,
+  // Type* Semantic(Type* t) { return Intersect(t,
   // MaskSemanticForTesting); }
-  TypeHandle Semantic(TypeHandle t) { return Type::Semantic(t, region_); }
+  Type* Semantic(Type* t) { return Type::Semantic(t, zone_); }
 
-  template<class Type2, class TypeHandle2>
-  TypeHandle Convert(TypeHandle2 t) {
-    return Type::template Convert<Type2>(t, region_);
-  }
-
-  TypeHandle Random() {
+  Type* Random() {
     return types[rng_->NextInt(static_cast<int>(types.size()))];
   }
 
-  TypeHandle Fuzz(int depth = 4) {
+  Type* Fuzz(int depth = 4) {
     switch (rng_->NextInt(depth == 0 ? 3 : 20)) {
       case 0: {  // bitset
         #define COUNT_BITSET_TYPES(type, value) + 1
         int n = 0 PROPER_BITSET_TYPE_LIST(COUNT_BITSET_TYPES);
         #undef COUNT_BITSET_TYPES
         // Pick a bunch of named bitsets and return their intersection.
-        TypeHandle result = Type::Any(region_);
+        Type* result = Type::Any();
         for (int i = 0, m = 1 + rng_->NextInt(3); i < m; ++i) {
           int j = rng_->NextInt(n);
-          #define PICK_BITSET_TYPE(type, value) \
-            if (j-- == 0) { \
-              TypeHandle tmp = Type::Intersect( \
-                  result, Type::type(region_), region_); \
-              if (tmp->Is(Type::None()) && i != 0) { \
-                break; \
-              } else { \
-                result = tmp; \
-                continue; \
-              } \
-            }
+#define PICK_BITSET_TYPE(type, value)                         \
+  if (j-- == 0) {                                             \
+    Type* tmp = Type::Intersect(result, Type::type(), zone_); \
+    if (tmp->Is(Type::None()) && i != 0) {                    \
+      break;                                                  \
+    } else {                                                  \
+      result = tmp;                                           \
+      continue;                                               \
+    }                                                         \
+  }
           PROPER_BITSET_TYPE_LIST(PICK_BITSET_TYPE)
           #undef PICK_BITSET_TYPE
         }
@@ -268,11 +243,11 @@
       }
       case 1: {  // class
         int i = rng_->NextInt(static_cast<int>(maps.size()));
-        return Type::Class(maps[i], region_);
+        return Type::Class(maps[i], zone_);
       }
       case 2: {  // constant
         int i = rng_->NextInt(static_cast<int>(values.size()));
-        return Type::Constant(values[i], region_);
+        return Type::Constant(values[i], zone_);
       }
       case 3: {  // range
         int i = rng_->NextInt(static_cast<int>(integers.size()));
@@ -280,26 +255,26 @@
         double min = integers[i]->Number();
         double max = integers[j]->Number();
         if (min > max) std::swap(min, max);
-        return Type::Range(min, max, region_);
+        return Type::Range(min, max, zone_);
       }
       case 4: {  // context
         int depth = rng_->NextInt(3);
-        TypeHandle type = Type::Internal(region_);
-        for (int i = 0; i < depth; ++i) type = Type::Context(type, region_);
+        Type* type = Type::Internal();
+        for (int i = 0; i < depth; ++i) type = Type::Context(type, zone_);
         return type;
       }
       case 5: {  // array
-        TypeHandle element = Fuzz(depth / 2);
-        return Type::Array(element, region_);
+        Type* element = Fuzz(depth / 2);
+        return Type::Array(element, zone_);
       }
       case 6:
       case 7: {  // function
-        TypeHandle result = Fuzz(depth / 2);
-        TypeHandle receiver = Fuzz(depth / 2);
+        Type* result = Fuzz(depth / 2);
+        Type* receiver = Fuzz(depth / 2);
         int arity = rng_->NextInt(3);
-        TypeHandle type = Type::Function(result, receiver, arity, region_);
+        Type* type = Type::Function(result, receiver, arity, zone_);
         for (int i = 0; i < type->AsFunction()->Arity(); ++i) {
-          TypeHandle parameter = Fuzz(depth / 2);
+          Type* parameter = Fuzz(depth / 2);
           type->AsFunction()->InitParameter(i, parameter);
         }
         return type;
@@ -309,21 +284,21 @@
             #define COUNT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) +1
             SIMD128_TYPES(COUNT_SIMD_TYPE);
             #undef COUNT_SIMD_TYPE
-        TypeHandle (*simd_constructors[num_simd_types])(Isolate*, Region*) = {
+        Type* (*simd_constructors[num_simd_types])(Isolate*, Zone*) = {
           #define COUNT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
           &Type::Name,
-          SIMD128_TYPES(COUNT_SIMD_TYPE)
+            SIMD128_TYPES(COUNT_SIMD_TYPE)
           #undef COUNT_SIMD_TYPE
         };
-        return simd_constructors[rng_->NextInt(num_simd_types)](
-            isolate_, region_);
+        return simd_constructors[rng_->NextInt(num_simd_types)](isolate_,
+                                                                zone_);
       }
       default: {  // union
         int n = rng_->NextInt(10);
-        TypeHandle type = None;
+        Type* type = None;
         for (int i = 0; i < n; ++i) {
-          TypeHandle operand = Fuzz(depth - 1);
-          type = Type::Union(type, operand, region_);
+          Type* operand = Fuzz(depth - 1);
+          type = Type::Union(type, operand, zone_);
         }
         return type;
       }
@@ -331,10 +306,10 @@
     UNREACHABLE();
   }
 
-  Region* region() { return region_; }
+  Zone* zone() { return zone_; }
 
  private:
-  Region* region_;
+  Zone* zone_;
   Isolate* isolate_;
   v8::base::RandomNumberGenerator* rng_;
 };
diff --git a/test/cctest/wasm/test-run-wasm-js.cc b/test/cctest/wasm/test-run-wasm-js.cc
index 6fcde64..0b33808 100644
--- a/test/cctest/wasm/test-run-wasm-js.cc
+++ b/test/cctest/wasm/test-run-wasm-js.cc
@@ -3,12 +3,14 @@
 // found in the LICENSE file.
 
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.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"
 
@@ -24,39 +26,79 @@
   } while (false)
 
 
-static uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig,
-                              const char* source) {
+#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).
+class PredictableInputValues {
+ public:
+  int base_;
+  explicit PredictableInputValues(int base) : base_(base) {}
+  double arg_d(int which) { return base_ * which + ((which & 1) * 0.5); }
+  float arg_f(int which) { return base_ * which + ((which & 1) * 0.25); }
+  int32_t arg_i(int which) { return base_ * which + ((which & 1) * kMinInt); }
+  int64_t arg_l(int which) {
+    return base_ * which + ((which & 1) * (0x04030201LL << 32));
+  }
+};
+
+
+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();
-  Handle<Code> code = CompileWasmToJSWrapper(isolate, module, jsfunc, index);
-  module->function_code->at(index) = code;
+  Handle<Code> code =
+      CompileWasmToJSWrapper(isolate, module, jsfunc, sig, "test");
+  module->instance->function_code->at(index) = code;
   return index;
 }
 
 
-static Handle<JSFunction> WrapCode(ModuleEnv* module, uint32_t index) {
+uint32_t AddJSSelector(TestingModule* module, FunctionSig* sig, int which) {
+  const int kMaxParams = 8;
+  static const char* formals[kMaxParams] = {
+      "",        "a",         "a,b",         "a,b,c",
+      "a,b,c,d", "a,b,c,d,e", "a,b,c,d,e,f", "a,b,c,d,e,f,g",
+  };
+  CHECK_LT(which, static_cast<int>(sig->parameter_count()));
+  CHECK_LT(static_cast<int>(sig->parameter_count()), kMaxParams);
+
+  i::EmbeddedVector<char, 256> source;
+  char param = 'a' + which;
+  SNPrintF(source, "(function(%s) { return %c; })",
+           formals[sig->parameter_count()], param);
+
+  return AddJsFunction(module, 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->function_code->at(index);
+  Handle<Code> code = module->instance->function_code->at(index);
   WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
   return compiler::CompileJSToWasmWrapper(isolate, module, name, code,
                                           module_object, index);
 }
 
 
-static void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a,
-                        double b) {
+void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc,
+                 Handle<Object>* buffer, int count) {
   Isolate* isolate = jsfunc->GetIsolate();
-  Handle<Object> buffer[] = {isolate->factory()->NewNumber(a),
-                             isolate->factory()->NewNumber(b)};
   Handle<Object> global(isolate->context()->global_object(), isolate);
   MaybeHandle<Object> retval =
-      Execution::Call(isolate, jsfunc, global, 2, buffer);
+      Execution::Call(isolate, jsfunc, global, count, buffer);
 
   CHECK(!retval.is_null());
   Handle<Object> result = retval.ToHandleChecked();
@@ -64,17 +106,26 @@
     CHECK_EQ(expected, Smi::cast(*result)->value());
   } else {
     CHECK(result->IsHeapNumber());
-    CHECK_EQ(expected, HeapNumber::cast(*result)->value());
+    CheckFloatEq(expected, HeapNumber::cast(*result)->value());
   }
 }
 
 
+void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a,
+                 double b) {
+  Isolate* isolate = jsfunc->GetIsolate();
+  Handle<Object> buffer[] = {isolate->factory()->NewNumber(a),
+                             isolate->factory()->NewNumber(b)};
+  EXPECT_CALL(expected, jsfunc, buffer, 2);
+}
+}  // namespace
+
 TEST(Run_Int32Sub_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
-  WasmFunctionCompiler t(sigs.i_ii());
+  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(&module));
+  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
 
   EXPECT_CALL(33, jsfunc, 44, 11);
   EXPECT_CALL(-8723487, jsfunc, -8000000, 723487);
@@ -84,9 +135,9 @@
 TEST(Run_Float32Div_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
-  WasmFunctionCompiler t(sigs.f_ff());
+  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(&module));
+  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
 
   EXPECT_CALL(92, jsfunc, 46, 0.5);
   EXPECT_CALL(64, jsfunc, -16, -0.25);
@@ -96,9 +147,9 @@
 TEST(Run_Float64Add_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
-  WasmFunctionCompiler t(sigs.d_dd());
+  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(&module));
+  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
 
   EXPECT_CALL(3, jsfunc, 2, 1);
   EXPECT_CALL(-5.5, jsfunc, -5.25, -0.25);
@@ -108,9 +159,9 @@
 TEST(Run_I32Popcount_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
-  WasmFunctionCompiler t(sigs.i_i());
+  WasmFunctionCompiler t(sigs.i_i(), &module);
   BUILD(t, WASM_I32_POPCNT(WASM_GET_LOCAL(0)));
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
+  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
 
   EXPECT_CALL(2, jsfunc, 9, 0);
   EXPECT_CALL(3, jsfunc, 11, 0);
@@ -121,8 +172,7 @@
 
 
 #if !V8_TARGET_ARCH_ARM64
-// TODO(titzer): fix wasm->JS calls on arm64 (wrapper issues)
-
+// TODO(titzer): dynamic frame alignment on arm64
 TEST(Run_CallJS_Add_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
@@ -131,11 +181,252 @@
       AddJsFunction(&module, sigs.i_i(), "(function(a) { return a + 99; })");
   BUILD(t, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0)));
 
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
+  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
 
   EXPECT_CALL(101, jsfunc, 2, -8);
   EXPECT_CALL(199, jsfunc, 100, -1);
   EXPECT_CALL(-666666801, jsfunc, -666666900, -1);
 }
+#endif
 
+
+void RunJSSelectTest(int which) {
+#if !V8_TARGET_ARCH_ARM
+  // TODO(titzer): fix tests on arm and reenable
+  const int kMaxParams = 8;
+  PredictableInputValues inputs(0x100);
+  LocalType type = kAstF64;
+  LocalType types[kMaxParams + 1] = {type, type, type, type, type,
+                                     type, type, type, type};
+  for (int num_params = which + 1; num_params < kMaxParams; num_params++) {
+    HandleScope scope(CcTest::InitIsolateOnce());
+    FunctionSig sig(1, num_params, types);
+
+    TestingModule module;
+    uint32_t js_index = AddJSSelector(&module, &sig, which);
+    WasmFunctionCompiler t(&sig, &module);
+
+    {
+      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)));
+      }
+
+      size_t end = code.size();
+      code.push_back(0);
+      t.Build(&code[0], &code[end]);
+    }
+
+    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+    double expected = inputs.arg_d(which);
+    EXPECT_CALL(expected, jsfunc, 0.0, 0.0);
+  }
+#endif
+}
+
+
+TEST(Run_JSSelect_0) { RunJSSelectTest(0); }
+
+TEST(Run_JSSelect_1) { RunJSSelectTest(1); }
+
+TEST(Run_JSSelect_2) { RunJSSelectTest(2); }
+
+TEST(Run_JSSelect_3) { RunJSSelectTest(3); }
+
+TEST(Run_JSSelect_4) { RunJSSelectTest(4); }
+
+TEST(Run_JSSelect_5) { RunJSSelectTest(5); }
+
+TEST(Run_JSSelect_6) { RunJSSelectTest(6); }
+
+TEST(Run_JSSelect_7) { RunJSSelectTest(7); }
+
+
+void RunWASMSelectTest(int which) {
+  PredictableInputValues inputs(0x200);
+  Isolate* isolate = CcTest::InitIsolateOnce();
+  const int kMaxParams = 8;
+  for (int num_params = which + 1; num_params < kMaxParams; num_params++) {
+    LocalType type = kAstF64;
+    LocalType types[kMaxParams + 1] = {type, type, type, type, type,
+                                       type, type, type, type};
+    FunctionSig sig(1, num_params, types);
+
+    TestingModule module;
+    WasmFunctionCompiler t(&sig, &module);
+    BUILD(t, WASM_GET_LOCAL(which));
+    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+
+    Handle<Object> args[] = {
+        isolate->factory()->NewNumber(inputs.arg_d(0)),
+        isolate->factory()->NewNumber(inputs.arg_d(1)),
+        isolate->factory()->NewNumber(inputs.arg_d(2)),
+        isolate->factory()->NewNumber(inputs.arg_d(3)),
+        isolate->factory()->NewNumber(inputs.arg_d(4)),
+        isolate->factory()->NewNumber(inputs.arg_d(5)),
+        isolate->factory()->NewNumber(inputs.arg_d(6)),
+        isolate->factory()->NewNumber(inputs.arg_d(7)),
+    };
+
+    double expected = inputs.arg_d(which);
+    EXPECT_CALL(expected, jsfunc, args, kMaxParams);
+  }
+}
+
+
+TEST(Run_WASMSelect_0) { RunWASMSelectTest(0); }
+
+TEST(Run_WASMSelect_1) { RunWASMSelectTest(1); }
+
+TEST(Run_WASMSelect_2) { RunWASMSelectTest(2); }
+
+TEST(Run_WASMSelect_3) { RunWASMSelectTest(3); }
+
+TEST(Run_WASMSelect_4) { RunWASMSelectTest(4); }
+
+TEST(Run_WASMSelect_5) { RunWASMSelectTest(5); }
+
+TEST(Run_WASMSelect_6) { RunWASMSelectTest(6); }
+
+TEST(Run_WASMSelect_7) { RunWASMSelectTest(7); }
+
+
+void RunWASMSelectAlignTest(int num_args, int num_params) {
+  PredictableInputValues inputs(0x300);
+  Isolate* isolate = CcTest::InitIsolateOnce();
+  const int kMaxParams = 4;
+  DCHECK_LE(num_args, kMaxParams);
+  LocalType type = kAstF64;
+  LocalType types[kMaxParams + 1] = {type, type, type, type, type};
+  FunctionSig sig(1, num_params, types);
+
+  for (int which = 0; which < num_params; which++) {
+    TestingModule module;
+    WasmFunctionCompiler t(&sig, &module);
+    BUILD(t, WASM_GET_LOCAL(which));
+    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+
+    Handle<Object> args[] = {
+        isolate->factory()->NewNumber(inputs.arg_d(0)),
+        isolate->factory()->NewNumber(inputs.arg_d(1)),
+        isolate->factory()->NewNumber(inputs.arg_d(2)),
+        isolate->factory()->NewNumber(inputs.arg_d(3)),
+    };
+
+    double nan = std::numeric_limits<double>::quiet_NaN();
+    double expected = which < num_args ? inputs.arg_d(which) : nan;
+    EXPECT_CALL(expected, jsfunc, args, num_args);
+  }
+}
+
+
+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);
+}
+
+
+void RunJSSelectAlignTest(int num_args, int num_params) {
+  PredictableInputValues inputs(0x400);
+  Isolate* isolate = CcTest::InitIsolateOnce();
+  Factory* factory = isolate->factory();
+  const int kMaxParams = 4;
+  CHECK_LE(num_args, kMaxParams);
+  CHECK_LE(num_params, kMaxParams);
+  LocalType type = kAstF64;
+  LocalType types[kMaxParams + 1] = {type, type, type, type, type};
+  FunctionSig sig(1, num_params, types);
+
+  // 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));
+  }
+
+  size_t end = code.size();
+  code.push_back(0);
+
+  // Call different select JS functions.
+  for (int which = 0; which < num_params; which++) {
+    HandleScope scope(isolate);
+    TestingModule module;
+    uint32_t js_index = AddJSSelector(&module, &sig, which);
+    CHECK_EQ(0, js_index);
+    WasmFunctionCompiler t(&sig, &module);
+    t.Build(&code[0], &code[end]);
+
+    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+
+    Handle<Object> args[] = {
+        factory->NewNumber(inputs.arg_d(0)),
+        factory->NewNumber(inputs.arg_d(1)),
+        factory->NewNumber(inputs.arg_d(2)),
+        factory->NewNumber(inputs.arg_d(3)),
+    };
+
+    double nan = std::numeric_limits<double>::quiet_NaN();
+    double expected = which < num_args ? inputs.arg_d(which) : nan;
+    EXPECT_CALL(expected, jsfunc, args, num_args);
+  }
+}
+
+
+TEST(Run_JSSelectAlign_0) {
+  RunJSSelectAlignTest(0, 1);
+  RunJSSelectAlignTest(0, 2);
+}
+
+
+TEST(Run_JSSelectAlign_2) {
+  RunJSSelectAlignTest(2, 3);
+  RunJSSelectAlignTest(2, 4);
+}
+
+
+TEST(Run_JSSelectAlign_4) {
+  RunJSSelectAlignTest(4, 3);
+  RunJSSelectAlignTest(4, 4);
+}
+
+
+#if !V8_TARGET_ARCH_ARM64
+// TODO(titzer): dynamic frame alignment on arm64
+TEST(Run_JSSelectAlign_1) {
+  RunJSSelectAlignTest(1, 2);
+  RunJSSelectAlignTest(1, 3);
+}
+
+
+TEST(Run_JSSelectAlign_3) {
+  RunJSSelectAlignTest(3, 3);
+  RunJSSelectAlignTest(3, 4);
+}
 #endif
diff --git a/test/cctest/wasm/test-run-wasm-module.cc b/test/cctest/wasm/test-run-wasm-module.cc
index 3b7bae1..905e8e4 100644
--- a/test/cctest/wasm/test-run-wasm-module.cc
+++ b/test/cctest/wasm/test-run-wasm-module.cc
@@ -6,6 +6,7 @@
 #include <string.h>
 
 #include "src/wasm/encoder.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"
@@ -18,9 +19,13 @@
 using namespace v8::internal::wasm;
 
 
+#if !V8_TARGET_ARCH_ARM64
+// TODO(titzer): fix arm64 frame alignment.
 namespace {
 void TestModule(WasmModuleIndex* module, int32_t expected_result) {
   Isolate* isolate = CcTest::InitIsolateOnce();
+  HandleScope scope(isolate);
+  WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
   int32_t result =
       CompileAndRunWasmModule(isolate, module->Begin(), module->End());
   CHECK_EQ(expected_result, result);
@@ -50,6 +55,8 @@
   };
 
   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);
@@ -197,3 +204,5 @@
   TestModule(writer->WriteTo(&zone), 97);
 }
 #endif
+
+#endif  // !V8_TARGET_ARCH_ARM64
diff --git a/test/cctest/wasm/test-run-wasm.cc b/test/cctest/wasm/test-run-wasm.cc
index 445c3f0..a6f07f7 100644
--- a/test/cctest/wasm/test-run-wasm.cc
+++ b/test/cctest/wasm/test-run-wasm.cc
@@ -26,7 +26,7 @@
 
 
 TEST(Run_WasmInt8Const) {
-  WasmRunner<int8_t> r;
+  WasmRunner<int32_t> r;
   const byte kExpectedValue = 121;
   // return(kExpectedValue)
   BUILD(r, WASM_I8(kExpectedValue));
@@ -35,7 +35,7 @@
 
 
 TEST(Run_WasmInt8Const_fallthru1) {
-  WasmRunner<int8_t> r;
+  WasmRunner<int32_t> r;
   const byte kExpectedValue = 122;
   // kExpectedValue
   BUILD(r, WASM_I8(kExpectedValue));
@@ -44,7 +44,7 @@
 
 
 TEST(Run_WasmInt8Const_fallthru2) {
-  WasmRunner<int8_t> r;
+  WasmRunner<int32_t> r;
   const byte kExpectedValue = 123;
   // -99 kExpectedValue
   BUILD(r, WASM_I8(-99), WASM_I8(kExpectedValue));
@@ -54,10 +54,10 @@
 
 TEST(Run_WasmInt8Const_all) {
   for (int value = -128; value <= 127; value++) {
-    WasmRunner<int8_t> r;
+    WasmRunner<int32_t> r;
     // return(value)
     BUILD(r, WASM_I8(value));
-    int8_t result = r.Call();
+    int32_t result = r.Call();
     CHECK_EQ(value, result);
   }
 }
@@ -84,10 +84,9 @@
 
 
 TEST(Run_WasmMemorySize) {
-  WasmRunner<int32_t> r;
   TestingModule module;
+  WasmRunner<int32_t> r(&module);
   module.AddMemory(1024);
-  r.env()->module = &module;
   BUILD(r, kExprMemorySize);
   CHECK_EQ(1024, r.Call());
 }
@@ -116,6 +115,23 @@
 }
 #endif
 
+TEST(Run_WasmI32ConvertI64) {
+  FOR_INT64_INPUTS(i) {
+    WasmRunner<int32_t> r;
+    BUILD(r, WASM_I32_CONVERT_I64(WASM_I64(*i)));
+    CHECK_EQ(static_cast<int32_t>(*i), r.Call());
+  }
+}
+
+TEST(Run_WasmI64AndConstants) {
+  FOR_INT64_INPUTS(i) {
+    FOR_INT64_INPUTS(j) {
+      WasmRunner<int32_t> r;
+      BUILD(r, WASM_I32_CONVERT_I64(WASM_I64_AND(WASM_I64(*i), WASM_I64(*j))));
+      CHECK_EQ(static_cast<int32_t>(*i & *j), r.Call());
+    }
+  }
+}
 
 TEST(Run_WasmInt32Param0) {
   WasmRunner<int32_t> r(MachineType::Int32());
@@ -179,9 +195,6 @@
 }
 
 
-// TODO(titzer): Fix for nosee4 and re-enable.
-#if 0
-
 TEST(Run_WasmFloat32Add) {
   WasmRunner<int32_t> r;
   // int(11.5f + 44.5f)
@@ -198,8 +211,6 @@
   CHECK_EQ(57, r.Call());
 }
 
-#endif
-
 
 void TestInt32Binop(WasmOpcode opcode, int32_t expected, int32_t a, int32_t b) {
   {
@@ -216,7 +227,6 @@
   }
 }
 
-
 TEST(Run_WasmInt32Binops) {
   TestInt32Binop(kExprI32Add, 88888888, 33333333, 55555555);
   TestInt32Binop(kExprI32Sub, -1111111, 7777777, 8888888);
@@ -594,10 +604,9 @@
 
 
 TEST(Run_WASM_Int32DivS_trap_effect) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
   TestingModule module;
   module.AddMemoryElems<int32_t>(8);
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
 
   BUILD(r,
         WASM_IF_ELSE(WASM_GET_LOCAL(0),
@@ -793,10 +802,6 @@
   }
 }
 
-
-// TODO(titzer): Fix for nosee4 and re-enable.
-#if 0
-
 TEST(Run_WasmFloat32Binops) {
   TestFloat32Binop(kExprF32Eq, 1, 8.125f, 8.125f);
   TestFloat32Binop(kExprF32Ne, 1, 8.125f, 8.127f);
@@ -811,7 +816,6 @@
   TestFloat32BinopWithConvert(kExprF32Div, 11, 22.1f, 2.0f);
 }
 
-
 TEST(Run_WasmFloat32Unops) {
   TestFloat32UnopWithConvert(kExprF32Abs, 8, 8.125f);
   TestFloat32UnopWithConvert(kExprF32Abs, 9, -9.125f);
@@ -819,7 +823,6 @@
   TestFloat32UnopWithConvert(kExprF32Sqrt, 12, 144.4f);
 }
 
-
 TEST(Run_WasmFloat64Binops) {
   TestFloat64Binop(kExprF64Eq, 1, 16.25, 16.25);
   TestFloat64Binop(kExprF64Ne, 1, 16.25, 16.15);
@@ -834,7 +837,6 @@
   TestFloat64BinopWithConvert(kExprF64Div, -1111, -2222.3, 2);
 }
 
-
 TEST(Run_WasmFloat64Unops) {
   TestFloat64UnopWithConvert(kExprF64Abs, 108, 108.125);
   TestFloat64UnopWithConvert(kExprF64Abs, 209, -209.125);
@@ -842,9 +844,6 @@
   TestFloat64UnopWithConvert(kExprF64Sqrt, 13, 169.4);
 }
 
-#endif
-
-
 TEST(Run_WasmFloat32Neg) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_NEG(WASM_GET_LOCAL(0)));
@@ -962,8 +961,8 @@
 
 TEST(Run_Wasm_Select) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  // return select(a, 11, 22);
-  BUILD(r, WASM_SELECT(WASM_GET_LOCAL(0), WASM_I8(11), WASM_I8(22)));
+  // return select(11, 22, a);
+  BUILD(r, WASM_SELECT(WASM_I8(11), WASM_I8(22), WASM_GET_LOCAL(0)));
   FOR_INT32_INPUTS(i) {
     int32_t expected = *i ? 11 : 22;
     CHECK_EQ(expected, r.Call(*i));
@@ -973,22 +972,38 @@
 
 TEST(Run_Wasm_Select_strict1) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  // select(a, a = 11, 22); return a
-  BUILD(r,
-        WASM_BLOCK(2, WASM_SELECT(WASM_GET_LOCAL(0),
-                                  WASM_SET_LOCAL(0, WASM_I8(11)), WASM_I8(22)),
-                   WASM_GET_LOCAL(0)));
-  FOR_INT32_INPUTS(i) { CHECK_EQ(11, r.Call(*i)); }
+  // select(a=0, a=1, a=2); return a
+  BUILD(r, WASM_BLOCK(2, WASM_SELECT(WASM_SET_LOCAL(0, WASM_I8(0)),
+                                     WASM_SET_LOCAL(0, WASM_I8(1)),
+                                     WASM_SET_LOCAL(0, WASM_I8(2))),
+                      WASM_GET_LOCAL(0)));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(2, r.Call(*i)); }
 }
 
 
 TEST(Run_Wasm_Select_strict2) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  // select(a, 11, a = 22); return a;
-  BUILD(r, WASM_BLOCK(2, WASM_SELECT(WASM_GET_LOCAL(0), WASM_I8(11),
-                                     WASM_SET_LOCAL(0, WASM_I8(22))),
-                      WASM_GET_LOCAL(0)));
-  FOR_INT32_INPUTS(i) { CHECK_EQ(22, r.Call(*i)); }
+  r.env()->AddLocals(kAstI32, 2);
+  // select(b=5, c=6, a)
+  BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)),
+                       WASM_SET_LOCAL(2, WASM_I8(6)), WASM_GET_LOCAL(0)));
+  FOR_INT32_INPUTS(i) {
+    int32_t expected = *i ? 5 : 6;
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
+
+TEST(Run_Wasm_Select_strict3) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  r.env()->AddLocals(kAstI32, 2);
+  // select(b=5, c=6, a=b)
+  BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)),
+                       WASM_SET_LOCAL(2, WASM_I8(6)),
+                       WASM_SET_LOCAL(0, WASM_GET_LOCAL(1))));
+  FOR_INT32_INPUTS(i) {
+    int32_t expected = 5;
+    CHECK_EQ(expected, r.Call(*i));
+  }
 }
 
 
@@ -1002,6 +1017,34 @@
   FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); }
 }
 
+TEST(Run_Wasm_TableSwitch0a) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, WASM_BLOCK(2, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(0)),
+                      WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), WASM_I8(91)));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(91, r.Call(*i)); }
+}
+
+TEST(Run_Wasm_TableSwitch0b) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, WASM_BLOCK(
+               2, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), WASM_CASE_BR(0)),
+               WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), WASM_I8(92)));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(92, r.Call(*i)); }
+}
+
+TEST(Run_Wasm_TableSwitch0c) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r,
+        WASM_BLOCK(2, WASM_BLOCK(2, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0),
+                                                        WASM_CASE_BR(1)),
+                                 WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)),
+                                 WASM_RETURN(WASM_I8(76))),
+                   WASM_I8(77)));
+  FOR_INT32_INPUTS(i) {
+    int32_t expected = *i == 0 ? 76 : 77;
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
 
 TEST(Run_Wasm_TableSwitch1) {
   WasmRunner<int32_t> r(MachineType::Int32());
@@ -1178,10 +1221,9 @@
 
 
 TEST(Run_Wasm_F32ReinterpretI32) {
-  WasmRunner<int32_t> r;
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module);
 
   BUILD(r, WASM_I32_REINTERPRET_F32(
                WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO)));
@@ -1195,10 +1237,9 @@
 
 
 TEST(Run_Wasm_I32ReinterpretF32) {
-  WasmRunner<int32_t> r(MachineType::Int32());
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
 
   BUILD(r, WASM_BLOCK(
                2, WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO,
@@ -1214,10 +1255,9 @@
 
 
 TEST(Run_Wasm_ReturnStore) {
-  WasmRunner<int32_t> r;
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module);
 
   BUILD(r, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO,
                           WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
@@ -1231,16 +1271,43 @@
 
 
 TEST(Run_Wasm_VoidReturn1) {
-  WasmRunner<void> r;
-  BUILD(r, kExprNop);
-  r.Call();
+  // We use a wrapper function because WasmRunner<void> does not exist.
+
+  // Build the test function.
+  TestSignatures sigs;
+  TestingModule module;
+  WasmFunctionCompiler t(sigs.v_v(), &module);
+  BUILD(t, kExprNop);
+  uint32_t index = t.CompileAndAdd();
+
+  const int32_t kExpected = -414444;
+  // Build the calling function.
+  WasmRunner<int32_t> r;
+  r.env()->module = &module;
+  BUILD(r, WASM_BLOCK(2, WASM_CALL_FUNCTION0(index), WASM_I32(kExpected)));
+
+  int32_t result = r.Call();
+  CHECK_EQ(kExpected, result);
 }
 
 
 TEST(Run_Wasm_VoidReturn2) {
-  WasmRunner<void> r;
-  BUILD(r, WASM_RETURN0);
-  r.Call();
+  // We use a wrapper function because WasmRunner<void> does not exist.
+  // Build the test function.
+  TestSignatures sigs;
+  TestingModule module;
+  WasmFunctionCompiler t(sigs.v_v(), &module);
+  BUILD(t, WASM_RETURN0);
+  uint32_t index = t.CompileAndAdd();
+
+  const int32_t kExpected = -414444;
+  // Build the calling function.
+  WasmRunner<int32_t> r;
+  r.env()->module = &module;
+  BUILD(r, WASM_BLOCK(2, WASM_CALL_FUNCTION0(index), WASM_I32(kExpected)));
+
+  int32_t result = r.Call();
+  CHECK_EQ(kExpected, result);
 }
 
 
@@ -1260,7 +1327,7 @@
 
 TEST(Run_Wasm_Block_BrIf_P) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(51)),
+  BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(51), WASM_GET_LOCAL(0)),
                       WASM_I8(52)));
   FOR_INT32_INPUTS(i) {
     int32_t expected = *i ? 51 : 52;
@@ -1427,11 +1494,10 @@
 
 
 TEST(Run_Wasm_LoadMemI32) {
-  WasmRunner<int32_t> r(MachineType::Int32());
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
   module.RandomizeMemory(1111);
-  r.env()->module = &module;
 
   BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(0)));
 
@@ -1447,11 +1513,10 @@
 
 
 TEST(Run_Wasm_LoadMemI32_oob) {
-  WasmRunner<int32_t> r(MachineType::Uint32());
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
+  WasmRunner<int32_t> r(&module, MachineType::Uint32());
   module.RandomizeMemory(1111);
-  r.env()->module = &module;
 
   BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
 
@@ -1468,12 +1533,11 @@
 
 
 TEST(Run_Wasm_LoadMemI32_oob_asm) {
-  WasmRunner<int32_t> r(MachineType::Uint32());
   TestingModule module;
   module.asm_js = true;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
+  WasmRunner<int32_t> r(&module, MachineType::Uint32());
   module.RandomizeMemory(1112);
-  r.env()->module = &module;
 
   BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
 
@@ -1502,8 +1566,7 @@
 
   for (size_t m = 0; m < arraysize(machineTypes); m++) {
     module.RandomizeMemory(1116 + static_cast<int>(m));
-    WasmRunner<int32_t> r(MachineType::Uint32());
-    r.env()->module = &module;
+    WasmRunner<int32_t> r(&module, MachineType::Uint32());
     uint32_t boundary = 24 - WasmOpcodes::MemSize(machineTypes[m]);
 
     BUILD(r, WASM_LOAD_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0)),
@@ -1519,11 +1582,10 @@
 
 
 TEST(Run_Wasm_LoadMemI32_offset) {
-  WasmRunner<int32_t> r(MachineType::Int32());
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(4);
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
   module.RandomizeMemory(1111);
-  r.env()->module = &module;
 
   BUILD(r, WASM_LOAD_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0)));
 
@@ -1545,18 +1607,17 @@
 }
 
 
-// TODO(titzer): Fix for mips and re-enable.
 #if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64
 
-TEST(Run_Wasm_LoadMemI32_const_oob) {
-  TestingModule module;
+TEST(Run_Wasm_LoadMemI32_const_oob_misaligned) {
   const int kMemSize = 12;
-  module.AddMemoryElems<byte>(kMemSize);
-
+  // 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++) {
-      WasmRunner<int32_t> r;
-      r.env()->module = &module;
+      TestingModule module;
+      module.AddMemoryElems<byte>(kMemSize);
+
+      WasmRunner<int32_t> r(&module);
       module.RandomizeMemory();
 
       BUILD(r,
@@ -1574,12 +1635,34 @@
 #endif
 
 
+TEST(Run_Wasm_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;
+      module.AddMemoryElems<byte>(kMemSize);
+
+      WasmRunner<int32_t> r(&module);
+      module.RandomizeMemory();
+
+      BUILD(r,
+            WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, WASM_I8(index)));
+
+      if ((offset + index) <= (kMemSize - sizeof(int32_t))) {
+        CHECK_EQ(module.raw_val_at<int32_t>(offset + index), r.Call());
+      } else {
+        CHECK_TRAP(r.Call());
+      }
+    }
+  }
+}
+
+
 TEST(Run_Wasm_StoreMemI32_offset) {
-  WasmRunner<int32_t> r(MachineType::Int32());
-  const int32_t kWritten = 0xaabbccdd;
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(4);
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
+  const int32_t kWritten = 0xaabbccdd;
 
   BUILD(r, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0),
                                  WASM_I32(kWritten)));
@@ -1618,8 +1701,7 @@
 
   for (size_t m = 0; m < arraysize(machineTypes); m++) {
     module.RandomizeMemory(1119 + static_cast<int>(m));
-    WasmRunner<int32_t> r(MachineType::Uint32());
-    r.env()->module = &module;
+    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)),
@@ -1639,10 +1721,9 @@
 
 #if WASM_64
 TEST(Run_Wasm_F64ReinterpretI64) {
-  WasmRunner<int64_t> r;
   TestingModule module;
   int64_t* memory = module.AddMemoryElems<int64_t>(8);
-  r.env()->module = &module;
+  WasmRunner<int64_t> r(&module);
 
   BUILD(r, WASM_I64_REINTERPRET_F64(
                WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO)));
@@ -1656,10 +1737,9 @@
 
 
 TEST(Run_Wasm_I64ReinterpretF64) {
-  WasmRunner<int64_t> r(MachineType::Int64());
   TestingModule module;
   int64_t* memory = module.AddMemoryElems<int64_t>(8);
-  r.env()->module = &module;
+  WasmRunner<int64_t> r(&module, MachineType::Int64());
 
   BUILD(r, WASM_BLOCK(
                2, WASM_STORE_MEM(MachineType::Float64(), WASM_ZERO,
@@ -1675,11 +1755,10 @@
 
 
 TEST(Run_Wasm_LoadMemI64) {
-  WasmRunner<int64_t> r;
   TestingModule module;
   int64_t* memory = module.AddMemoryElems<int64_t>(8);
   module.RandomizeMemory(1111);
-  r.env()->module = &module;
+  WasmRunner<int64_t> r(&module);
 
   BUILD(r, WASM_LOAD_MEM(MachineType::Int64(), WASM_I8(0)));
 
@@ -1697,11 +1776,10 @@
 
 TEST(Run_Wasm_LoadMemI32_P) {
   const int kNumElems = 8;
-  WasmRunner<int32_t> r(MachineType::Int32());
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(kNumElems);
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
   module.RandomizeMemory(2222);
-  r.env()->module = &module;
 
   BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
 
@@ -1712,12 +1790,11 @@
 
 
 TEST(Run_Wasm_MemI32_Sum) {
-  WasmRunner<uint32_t> r(MachineType::Int32());
   const int kNumElems = 20;
-  const byte kSum = r.AllocateLocal(kAstI32);
   TestingModule module;
   uint32_t* memory = module.AddMemoryElems<uint32_t>(kNumElems);
-  r.env()->module = &module;
+  WasmRunner<uint32_t> r(&module, MachineType::Int32());
+  const byte kSum = r.AllocateLocal(kAstI32);
 
   BUILD(r, WASM_BLOCK(
                2, WASM_WHILE(
@@ -1746,11 +1823,10 @@
 
 
 TEST(Run_Wasm_CheckMachIntsZero) {
-  WasmRunner<uint32_t> r(MachineType::Int32());
   const int kNumElems = 55;
   TestingModule module;
   module.AddMemoryElems<uint32_t>(kNumElems);
-  r.env()->module = &module;
+  WasmRunner<uint32_t> r(&module, MachineType::Int32());
 
   BUILD(r, kExprBlock, 2, kExprLoop, 1, kExprIf, kExprGetLocal, 0, kExprBr, 0,
         kExprIfElse, kExprI32LoadMem, 0, kExprGetLocal, 0, kExprBr, 2,
@@ -1763,8 +1839,6 @@
 
 
 TEST(Run_Wasm_MemF32_Sum) {
-  WasmRunner<int32_t> r(MachineType::Int32());
-  const byte kSum = r.AllocateLocal(kAstF32);
   const int kSize = 5;
   TestingModule module;
   module.AddMemoryElems<float>(kSize);
@@ -1774,7 +1848,8 @@
   buffer[2] = -77.25;
   buffer[3] = 66666.25;
   buffer[4] = 5555.25;
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
+  const byte kSum = r.AllocateLocal(kAstF32);
 
   BUILD(r, WASM_BLOCK(
                3, WASM_WHILE(
@@ -1799,12 +1874,11 @@
 
 #if WASM_64
 TEST(Run_Wasm_MemI64_Sum) {
-  WasmRunner<uint64_t> r(MachineType::Int32());
   const int kNumElems = 20;
-  const byte kSum = r.AllocateLocal(kAstI64);
   TestingModule module;
   uint64_t* memory = module.AddMemoryElems<uint64_t>(kNumElems);
-  r.env()->module = &module;
+  WasmRunner<uint64_t> r(&module, MachineType::Int32());
+  const byte kSum = r.AllocateLocal(kAstI64);
 
   BUILD(r, WASM_BLOCK(
                2, WASM_WHILE(
@@ -1836,14 +1910,13 @@
 template <typename T>
 T GenerateAndRunFold(WasmOpcode binop, T* buffer, size_t size,
                      LocalType astType, MachineType memType) {
-  WasmRunner<int32_t> r(MachineType::Int32());
-  const byte kAccum = r.AllocateLocal(astType);
   TestingModule module;
   module.AddMemoryElems<T>(size);
   for (size_t i = 0; i < size; i++) {
     module.raw_mem_start<T>()[i] = buffer[i];
   }
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
+  const byte kAccum = r.AllocateLocal(astType);
 
   BUILD(
       r,
@@ -1882,10 +1955,9 @@
 
 
 TEST(Build_Wasm_Infinite_Loop_effect) {
-  WasmRunner<int32_t> r(MachineType::Int32());
   TestingModule module;
   module.AddMemoryElems<int8_t>(16);
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
 
   // Only build the graph and compile, don't run.
   BUILD(r, WASM_LOOP(1, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
@@ -1970,7 +2042,7 @@
 
 TEST(Run_Wasm_Infinite_Loop_not_taken2_brif) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(45)),
+  BUILD(r, WASM_BLOCK(2, 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));
@@ -2022,8 +2094,7 @@
   int8_t* memory = module.AddMemoryElems<int8_t>(kNumElems);
   module.RandomizeMemory();
   memory[0] = -1;
-  WasmRunner<int32_t> r(MachineType::Int32());
-  r.env()->module = &module;
+  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++) {
@@ -2038,8 +2109,7 @@
   byte* memory = module.AddMemory(kNumElems);
   module.RandomizeMemory(77);
   memory[0] = 255;
-  WasmRunner<int32_t> r(MachineType::Int32());
-  r.env()->module = &module;
+  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++) {
@@ -2054,8 +2124,7 @@
   byte* memory = module.AddMemory(kNumBytes);
   module.RandomizeMemory(888);
   memory[1] = 200;
-  WasmRunner<int32_t> r(MachineType::Int32());
-  r.env()->module = &module;
+  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) {
@@ -2071,8 +2140,7 @@
   byte* memory = module.AddMemory(kNumBytes);
   module.RandomizeMemory(9999);
   memory[1] = 204;
-  WasmRunner<int32_t> r(MachineType::Int32());
-  r.env()->module = &module;
+  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) {
@@ -2085,8 +2153,7 @@
 TEST(Run_WasmInt32Global) {
   TestingModule module;
   int32_t* global = module.AddGlobal<int32_t>(MachineType::Int32());
-  WasmRunner<int32_t> r(MachineType::Int32());
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
   // global = global + p0
   BUILD(r, WASM_STORE_GLOBAL(
                0, WASM_I32_ADD(WASM_LOAD_GLOBAL(0), WASM_GET_LOCAL(0))));
@@ -2109,8 +2176,7 @@
 
   for (int g = 0; g < kNumGlobals; g++) {
     // global = global + p0
-    WasmRunner<int32_t> r(MachineType::Int32());
-    r.env()->module = &module;
+    WasmRunner<int32_t> r(&module, MachineType::Int32());
     BUILD(r, WASM_STORE_GLOBAL(
                  g, WASM_I32_ADD(WASM_LOAD_GLOBAL(g), WASM_GET_LOCAL(0))));
 
@@ -2134,8 +2200,7 @@
 TEST(Run_WasmInt64Global) {
   TestingModule module;
   int64_t* global = module.AddGlobal<int64_t>(MachineType::Int64());
-  WasmRunner<int32_t> r(MachineType::Int32());
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
   // global = global + p0
   BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL(
                              0, WASM_I64_ADD(
@@ -2156,8 +2221,7 @@
 TEST(Run_WasmFloat32Global) {
   TestingModule module;
   float* global = module.AddGlobal<float>(MachineType::Float32());
-  WasmRunner<int32_t> r(MachineType::Int32());
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
   // global = global + p0
   BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL(
                              0, WASM_F32_ADD(
@@ -2177,8 +2241,7 @@
 TEST(Run_WasmFloat64Global) {
   TestingModule module;
   double* global = module.AddGlobal<double>(MachineType::Float64());
-  WasmRunner<int32_t> r(MachineType::Int32());
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
   // global = global + p0
   BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL(
                              0, WASM_F64_ADD(
@@ -2209,8 +2272,7 @@
   float* var_float = module.AddGlobal<float>(MachineType::Float32());
   double* var_double = module.AddGlobal<double>(MachineType::Float64());
 
-  WasmRunner<int32_t> r(MachineType::Int32());
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
 
   BUILD(
       r,
@@ -2312,13 +2374,12 @@
   // Build the target function.
   TestSignatures sigs;
   TestingModule module;
-  WasmFunctionCompiler t(sigs.i_v());
+  WasmFunctionCompiler t(sigs.i_v(), &module);
   BUILD(t, WASM_I32(kExpected));
-  uint32_t index = t.CompileAndAdd(&module);
+  uint32_t index = t.CompileAndAdd();
 
   // Build the calling function.
-  WasmRunner<int32_t> r;
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module);
   BUILD(r, WASM_CALL_FUNCTION0(index));
 
   int32_t result = r.Call();
@@ -2326,22 +2387,18 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST(Run_WasmCallF32StackParameter) {
   // Build the target function.
   LocalType param_types[20];
   for (int i = 0; i < 20; i++) param_types[i] = kAstF32;
   FunctionSig sig(1, 19, param_types);
   TestingModule module;
-  WasmFunctionCompiler t(&sig);
+  WasmFunctionCompiler t(&sig, &module);
   BUILD(t, WASM_GET_LOCAL(17));
-  uint32_t index = t.CompileAndAdd(&module);
+  uint32_t index = t.CompileAndAdd();
 
   // Build the calling function.
-  WasmRunner<float> r;
-  r.env()->module = &module;
+  WasmRunner<float> r(&module);
   BUILD(r, WASM_CALL_FUNCTION(
                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),
@@ -2361,13 +2418,12 @@
   for (int i = 0; i < 20; i++) param_types[i] = kAstF64;
   FunctionSig sig(1, 19, param_types);
   TestingModule module;
-  WasmFunctionCompiler t(&sig);
+  WasmFunctionCompiler t(&sig, &module);
   BUILD(t, WASM_GET_LOCAL(17));
-  uint32_t index = t.CompileAndAdd(&module);
+  uint32_t index = t.CompileAndAdd();
 
   // Build the calling function.
-  WasmRunner<double> r;
-  r.env()->module = &module;
+  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),
@@ -2380,8 +2436,50 @@
   CHECK_EQ(256.5, result);
 }
 
-#endif
+TEST(Run_WasmCallI64Parameter) {
+  // Build the target function.
+  LocalType param_types[20];
+  for (int i = 0; i < 20; i++) param_types[i] = kAstI64;
+  param_types[3] = kAstI32;
+  param_types[4] = kAstI32;
+  FunctionSig sig(1, 19, param_types);
+  for (int i = 0; i < 19; i++) {
+    TestingModule module;
+    WasmFunctionCompiler t(&sig, &module);
+    if (i == 2 || i == 3) {
+      continue;
+    } else {
+      BUILD(t, WASM_GET_LOCAL(i));
+    }
+    uint32_t index = t.CompileAndAdd();
 
+    // Build the calling function.
+    WasmRunner<int32_t> r;
+    r.env()->module = &module;
+    BUILD(r,
+          WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION(
+              index, WASM_I64(0xbcd12340000000b), WASM_I64(0xbcd12340000000c),
+              WASM_I32(0xd), WASM_I32_CONVERT_I64(WASM_I64(0xbcd12340000000e)),
+              WASM_I64(0xbcd12340000000f), WASM_I64(0xbcd1234000000010),
+              WASM_I64(0xbcd1234000000011), WASM_I64(0xbcd1234000000012),
+              WASM_I64(0xbcd1234000000013), WASM_I64(0xbcd1234000000014),
+              WASM_I64(0xbcd1234000000015), WASM_I64(0xbcd1234000000016),
+              WASM_I64(0xbcd1234000000017), WASM_I64(0xbcd1234000000018),
+              WASM_I64(0xbcd1234000000019), WASM_I64(0xbcd123400000001a),
+              WASM_I64(0xbcd123400000001b), WASM_I64(0xbcd123400000001c),
+              WASM_I64(0xbcd123400000001d))));
+
+    CHECK_EQ(i + 0xb, r.Call());
+  }
+}
+
+TEST(Run_WasmI64And) {
+  WasmRunner<int64_t> r(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)); }
+  }
+}
 
 TEST(Run_WasmCallVoid) {
   const byte kMemOffset = 8;
@@ -2392,15 +2490,13 @@
   TestingModule module;
   module.AddMemory(16);
   module.RandomizeMemory();
-  WasmFunctionCompiler t(sigs.v_v());
-  t.env.module = &module;
+  WasmFunctionCompiler t(sigs.v_v(), &module);
   BUILD(t, WASM_STORE_MEM(MachineType::Int32(), WASM_I8(kMemOffset),
                           WASM_I32(kExpected)));
-  uint32_t index = t.CompileAndAdd(&module);
+  uint32_t index = t.CompileAndAdd();
 
   // Build the calling function.
-  WasmRunner<int32_t> r;
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module);
   BUILD(r, WASM_CALL_FUNCTION0(index),
         WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kMemOffset)));
 
@@ -2414,13 +2510,12 @@
   // Build the target function.
   TestSignatures sigs;
   TestingModule module;
-  WasmFunctionCompiler t(sigs.i_ii());
+  WasmFunctionCompiler t(sigs.i_ii(), &module);
   BUILD(t, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  uint32_t index = t.CompileAndAdd(&module);
+  uint32_t index = t.CompileAndAdd();
 
   // Build the caller function.
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
   BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_INT32_INPUTS(i) {
@@ -2438,13 +2533,12 @@
   // Build the target function.
   TestSignatures sigs;
   TestingModule module;
-  WasmFunctionCompiler t(sigs.l_ll());
+  WasmFunctionCompiler t(sigs.l_ll(), &module);
   BUILD(t, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  uint32_t index = t.CompileAndAdd(&module);
+  uint32_t index = t.CompileAndAdd();
 
   // Build the caller function.
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
-  r.env()->module = &module;
+  WasmRunner<int64_t> r(&module, MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_INT32_INPUTS(i) {
@@ -2465,16 +2559,15 @@
 
 TEST(Run_WasmCall_Float32Sub) {
   TestSignatures sigs;
-  WasmFunctionCompiler t(sigs.f_ff());
+  TestingModule module;
+  WasmFunctionCompiler t(sigs.f_ff(), &module);
 
   // Build the target function.
-  TestingModule module;
   BUILD(t, WASM_F32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  uint32_t index = t.CompileAndAdd(&module);
+  uint32_t index = t.CompileAndAdd();
 
   // Builder the caller function.
-  WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
-  r.env()->module = &module;
+  WasmRunner<float> r(&module, MachineType::Float32(), MachineType::Float32());
   BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -2487,10 +2580,9 @@
 
 
 TEST(Run_WasmCall_Float64Sub) {
-  WasmRunner<int32_t> r;
   TestingModule module;
   double* memory = module.AddMemoryElems<double>(16);
-  r.env()->module = &module;
+  WasmRunner<int32_t> r(&module);
 
   // TODO(titzer): convert to a binop test.
   BUILD(r, WASM_BLOCK(
@@ -2560,36 +2652,32 @@
     for (int i = 0; i < num_params; i++) {
       b.AddParam(WasmOpcodes::LocalTypeFor(memtypes[i]));
     }
-    WasmFunctionCompiler t(b.Build());
-    t.env.module = &module;
+    WasmFunctionCompiler t(b.Build(), &module);
     BUILD(t, WASM_GET_LOCAL(which));
-    index = t.CompileAndAdd(&module);
+    index = t.CompileAndAdd();
 
     // =========================================================================
     // Build the calling function.
     // =========================================================================
-    WasmRunner<int32_t> r;
-    r.env()->module = &module;
+    WasmRunner<int32_t> r(&module);
 
-    {
-      std::vector<byte> code;
-      ADD_CODE(code,
-               static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
-               WasmOpcodes::LoadStoreAccessOf(false));
-      ADD_CODE(code, WASM_ZERO);
-      ADD_CODE(code, kExprCallFunction, static_cast<byte>(index));
+    std::vector<byte> code;
+    ADD_CODE(code,
+             static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
+             WasmOpcodes::LoadStoreAccessOf(false));
+    ADD_CODE(code, WASM_ZERO);
+    ADD_CODE(code, kExprCallFunction, static_cast<byte>(index));
 
-      for (int i = 0; i < num_params; i++) {
-        int offset = (i + 1) * kElemSize;
-        ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset)));
-      }
-
-      ADD_CODE(code, WASM_I32(kExpected));
-      size_t end = code.size();
-      code.push_back(0);
-      r.Build(&code[0], &code[end]);
+    for (int i = 0; i < num_params; i++) {
+      int offset = (i + 1) * kElemSize;
+      ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset)));
     }
 
+    ADD_CODE(code, WASM_I32(kExpected));
+    size_t end = code.size();
+    code.push_back(0);
+    r.Build(&code[0], &code[end]);
+
     // Run the code.
     for (int t = 0; t < 10; t++) {
       module.RandomizeMemory();
@@ -2612,6 +2700,27 @@
 TEST(Run_WasmMixedCall_2) { Run_WasmMixedCall_N(2); }
 TEST(Run_WasmMixedCall_3) { Run_WasmMixedCall_N(3); }
 
+TEST(Run_Wasm_AddCall) {
+  TestSignatures sigs;
+  TestingModule module;
+  WasmFunctionCompiler t1(sigs.i_ii(), &module);
+  BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  t1.CompileAndAdd();
+
+  WasmRunner<int32_t> r(&module, MachineType::Int32());
+  byte local = r.AllocateLocal(kAstI32);
+  BUILD(r,
+        WASM_BLOCK(2, 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)))));
+
+  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());
@@ -2646,7 +2755,7 @@
 
 TEST(Run_Wasm_ExprBlock2c) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(1)),
+  BUILD(r, WASM_BLOCK(2, 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));
@@ -2655,7 +2764,7 @@
 
 TEST(Run_Wasm_ExprBlock2d) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(1)),
+  BUILD(r, WASM_BLOCK(2, 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));
@@ -2688,16 +2797,16 @@
 TEST(Run_Wasm_ExprBlock_ManualSwitch_brif) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r,
-        WASM_BLOCK(6, WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)),
-                                  WASM_I8(11)),
-                   WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)),
-                               WASM_I8(12)),
-                   WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)),
-                               WASM_I8(13)),
-                   WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)),
-                               WASM_I8(14)),
-                   WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)),
-                               WASM_I8(15)),
+        WASM_BLOCK(6, WASM_BRV_IF(0, WASM_I8(11),
+                                  WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1))),
+                   WASM_BRV_IF(0, WASM_I8(12),
+                               WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2))),
+                   WASM_BRV_IF(0, WASM_I8(13),
+                               WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3))),
+                   WASM_BRV_IF(0, WASM_I8(14),
+                               WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4))),
+                   WASM_BRV_IF(0, WASM_I8(15),
+                               WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5))),
                    WASM_I8(99)));
   CHECK_EQ(99, r.Call(0));
   CHECK_EQ(11, r.Call(1));
@@ -2781,10 +2890,9 @@
                   kExprI64LoadMem};
 
   for (size_t m = 0; m < arraysize(loads); m++) {
-    WasmRunner<int64_t> r;
     TestingModule module;
     byte* memory = module.AddMemoryElems<byte>(16);
-    r.env()->module = &module;
+    WasmRunner<int64_t> r(&module);
 
     byte code[] = {kExprI64StoreMem, 0, kExprI8Const, 8,
                    loads[m],         0, kExprI8Const, 0};
@@ -2813,19 +2921,16 @@
 
 
 TEST(Run_Wasm_SimpleCallIndirect) {
-  Isolate* isolate = CcTest::InitIsolateOnce();
-
-  WasmRunner<int32_t> r(MachineType::Int32());
   TestSignatures sigs;
   TestingModule module;
-  r.env()->module = &module;
-  WasmFunctionCompiler t1(sigs.i_ii());
-  BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  t1.CompileAndAdd(&module);
 
-  WasmFunctionCompiler t2(sigs.i_ii());
+  WasmFunctionCompiler t1(sigs.i_ii(), &module);
+  BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  t1.CompileAndAdd(/*sig_index*/ 1);
+
+  WasmFunctionCompiler t2(sigs.i_ii(), &module);
   BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  t2.CompileAndAdd(&module);
+  t2.CompileAndAdd(/*sig_index*/ 1);
 
   // Signature table.
   module.AddSignature(sigs.f_ff());
@@ -2833,20 +2938,12 @@
   module.AddSignature(sigs.d_dd());
 
   // Function table.
-  int table_size = 2;
-  module.module->function_table = new std::vector<uint16_t>;
-  module.module->function_table->push_back(0);
-  module.module->function_table->push_back(1);
-
-  // Function table.
-  Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size);
-  fixed->set(0, Smi::FromInt(1));
-  fixed->set(1, Smi::FromInt(1));
-  fixed->set(2, *module.function_code->at(0));
-  fixed->set(3, *module.function_code->at(1));
-  module.function_table = fixed;
+  int table[] = {0, 1};
+  module.AddIndirectFunctionTable(table, 2);
+  module.PopulateIndirectFunctionTable();
 
   // 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)));
 
   CHECK_EQ(88, r.Call(0));
@@ -2856,20 +2953,16 @@
 
 
 TEST(Run_Wasm_MultipleCallIndirect) {
-  Isolate* isolate = CcTest::InitIsolateOnce();
-
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32(),
-                        MachineType::Int32());
   TestSignatures sigs;
   TestingModule module;
-  r.env()->module = &module;
-  WasmFunctionCompiler t1(sigs.i_ii());
-  BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  t1.CompileAndAdd(&module);
 
-  WasmFunctionCompiler t2(sigs.i_ii());
+  WasmFunctionCompiler t1(sigs.i_ii(), &module);
+  BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  t1.CompileAndAdd(/*sig_index*/ 1);
+
+  WasmFunctionCompiler t2(sigs.i_ii(), &module);
   BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  t2.CompileAndAdd(&module);
+  t2.CompileAndAdd(/*sig_index*/ 1);
 
   // Signature table.
   module.AddSignature(sigs.f_ff());
@@ -2877,20 +2970,13 @@
   module.AddSignature(sigs.d_dd());
 
   // Function table.
-  int table_size = 2;
-  module.module->function_table = new std::vector<uint16_t>;
-  module.module->function_table->push_back(0);
-  module.module->function_table->push_back(1);
-
-  // Function table.
-  Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size);
-  fixed->set(0, Smi::FromInt(1));
-  fixed->set(1, Smi::FromInt(1));
-  fixed->set(2, *module.function_code->at(0));
-  fixed->set(3, *module.function_code->at(1));
-  module.function_table = fixed;
+  int table[] = {0, 1};
+  module.AddIndirectFunctionTable(table, 2);
+  module.PopulateIndirectFunctionTable();
 
   // 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)),
@@ -2908,42 +2994,56 @@
   CHECK_TRAP(r.Call(2, 1, 0));
 }
 
+TEST(Run_Wasm_CallIndirect_NoTable) {
+  TestSignatures sigs;
+  TestingModule module;
 
-// TODO(titzer): Fix for nosee4 and re-enable.
-#if 0
+  // One function.
+  WasmFunctionCompiler t1(sigs.i_ii(), &module);
+  BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  t1.CompileAndAdd(/*sig_index*/ 1);
+
+  // Signature table.
+  module.AddSignature(sigs.f_ff());
+  module.AddSignature(sigs.i_ii());
+
+  // 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)));
+
+  CHECK_TRAP(r.Call(0));
+  CHECK_TRAP(r.Call(1));
+  CHECK_TRAP(r.Call(2));
+}
 
 TEST(Run_Wasm_F32Floor) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0)));
 
-  FOR_FLOAT32_INPUTS(i) { CheckFloatEq(floor(*i), r.Call(*i)); }
+  FOR_FLOAT32_INPUTS(i) { CheckFloatEq(floorf(*i), r.Call(*i)); }
 }
 
-
 TEST(Run_Wasm_F32Ceil) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0)));
 
-  FOR_FLOAT32_INPUTS(i) { CheckFloatEq(ceil(*i), r.Call(*i)); }
+  FOR_FLOAT32_INPUTS(i) { CheckFloatEq(ceilf(*i), r.Call(*i)); }
 }
 
-
 TEST(Run_Wasm_F32Trunc) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
 
-  FOR_FLOAT32_INPUTS(i) { CheckFloatEq(trunc(*i), r.Call(*i)); }
+  FOR_FLOAT32_INPUTS(i) { CheckFloatEq(truncf(*i), r.Call(*i)); }
 }
 
-
 TEST(Run_Wasm_F32NearestInt) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0)));
 
-  FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyint(*i), r.Call(*i)); }
+  FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyintf(*i), r.Call(*i)); }
 }
 
-
 TEST(Run_Wasm_F64Floor) {
   WasmRunner<double> r(MachineType::Float64());
   BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0)));
@@ -2951,7 +3051,6 @@
   FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(floor(*i), r.Call(*i)); }
 }
 
-
 TEST(Run_Wasm_F64Ceil) {
   WasmRunner<double> r(MachineType::Float64());
   BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0)));
@@ -2959,7 +3058,6 @@
   FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(ceil(*i), r.Call(*i)); }
 }
 
-
 TEST(Run_Wasm_F64Trunc) {
   WasmRunner<double> r(MachineType::Float64());
   BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
@@ -2967,7 +3065,6 @@
   FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); }
 }
 
-
 TEST(Run_Wasm_F64NearestInt) {
   WasmRunner<double> r(MachineType::Float64());
   BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0)));
@@ -2975,9 +3072,6 @@
   FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(nearbyint(*i), r.Call(*i)); }
 }
 
-#endif
-
-
 TEST(Run_Wasm_F32Min) {
   WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
   BUILD(r, WASM_F32_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -3073,6 +3167,74 @@
   }
 }
 
+// TODO(ahaas): Fix on arm and reenable.
+#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
+
+TEST(Run_Wasm_F32Min_Snan) {
+  // Test that the instruction does not return a signalling NaN.
+  {
+    WasmRunner<float> r;
+    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;
+    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) {
+  // Test that the instruction does not return a signalling NaN.
+  {
+    WasmRunner<float> r;
+    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;
+    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) {
+  // Test that the instruction does not return a signalling NaN.
+  {
+    WasmRunner<double> r;
+    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;
+    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) {
+  // Test that the instruction does not return a signalling NaN.
+  {
+    WasmRunner<double> r;
+    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;
+    BUILD(r, WASM_F64_MAX(WASM_F64(45.73),
+                          WASM_F64(bit_cast<double>(0x7ff000000000f1e2))));
+    CHECK_EQ(0x7ff800000000f1e2, bit_cast<uint64_t>(r.Call()));
+  }
+}
+
+#endif
 
 #if WASM_64
 TEST(Run_Wasm_F32SConvertI64) {
@@ -3251,4 +3413,48 @@
   }
 }
 
+
 #endif
+
+
+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++) {
+    Zone zone;
+    HandleScope scope(CcTest::InitIsolateOnce());
+    TestingModule module;
+    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, kExprCallIndirect, 1);
+    ADD_CODE(code, kExprI8Const, 0);
+    for (byte p = 0; p < num_params; p++) {
+      ADD_CODE(code, kExprGetLocal, p);
+    }
+
+    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); }
diff --git a/test/cctest/wasm/test-signatures.h b/test/cctest/wasm/test-signatures.h
index 30ea605..a5bc7b4 100644
--- a/test/cctest/wasm/test-signatures.h
+++ b/test/cctest/wasm/test-signatures.h
@@ -72,6 +72,15 @@
   FunctionSig* v_ii() { return &sig_v_ii; }
   FunctionSig* v_iii() { return &sig_v_iii; }
 
+  FunctionSig* many(Zone* zone, LocalType ret, LocalType param, int count) {
+    FunctionSig::Builder builder(zone, ret == kAstStmt ? 0 : 1, count);
+    if (ret != kAstStmt) builder.AddReturn(ret);
+    for (int i = 0; i < count; i++) {
+      builder.AddParam(param);
+    }
+    return builder.Build();
+  }
+
  private:
   LocalType kIntTypes4[4];
   LocalType kLongTypes4[4];
diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h
index cc23b46..7ee3981 100644
--- a/test/cctest/wasm/wasm-run-utils.h
+++ b/test/cctest/wasm/wasm-run-utils.h
@@ -12,7 +12,10 @@
 #include "src/base/utils/random-number-generator.h"
 
 #include "src/compiler/graph-visualizer.h"
+#include "src/compiler/int64-lowering.h"
 #include "src/compiler/js-graph.h"
+#include "src/compiler/node.h"
+#include "src/compiler/pipeline.h"
 #include "src/compiler/wasm-compiler.h"
 
 #include "src/wasm/ast-decoder.h"
@@ -20,8 +23,10 @@
 #include "src/wasm/wasm-module.h"
 #include "src/wasm/wasm-opcodes.h"
 
+#include "src/zone.h"
+
 #include "test/cctest/cctest.h"
-#include "test/cctest/compiler/codegen-tester.h"
+#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.
@@ -31,6 +36,8 @@
 #define WASM_64 0
 #endif
 
+static const uint32_t kMaxFunctions = 10;
+
 // 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
@@ -41,6 +48,9 @@
   CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
 #define CHECK_TRAP(x) CHECK_TRAP32(x)
 
+#define WASM_RUNNER_MAX_NUM_PARAMETERS 4
+#define WASM_WRAPPER_RETURN_VALUE 8754
+
 namespace {
 using namespace v8::base;
 using namespace v8::internal;
@@ -50,47 +60,51 @@
 inline void init_env(FunctionEnv* env, FunctionSig* sig) {
   env->module = nullptr;
   env->sig = sig;
-  env->local_int32_count = 0;
-  env->local_int64_count = 0;
-  env->local_float32_count = 0;
-  env->local_float64_count = 0;
+  env->local_i32_count = 0;
+  env->local_i64_count = 0;
+  env->local_f32_count = 0;
+  env->local_f64_count = 0;
   env->SumLocals();
 }
 
 const uint32_t kMaxGlobalsSize = 128;
 
 // A helper for module environments that adds the ability to allocate memory
-// and global variables.
+// and global variables. Contains a built-in {WasmModule} and
+// {WasmModuleInstance}.
 class TestingModule : public ModuleEnv {
  public:
-  TestingModule() : mem_size(0), global_offset(0) {
-    globals_area = 0;
-    mem_start = 0;
-    mem_end = 0;
-    module = nullptr;
+  TestingModule() : instance_(&module_), global_offset(0) {
+    module_.shared_isolate = CcTest::InitIsolateOnce();
+    module = &module_;
+    instance = &instance_;
+    instance->module = &module_;
+    instance->globals_start = global_data;
+    instance->globals_size = kMaxGlobalsSize;
+    instance->mem_start = nullptr;
+    instance->mem_size = 0;
+    instance->function_code = nullptr;
     linker = nullptr;
-    function_code = nullptr;
     asm_js = false;
     memset(global_data, 0, sizeof(global_data));
   }
 
   ~TestingModule() {
-    if (mem_start) {
-      free(raw_mem_start<byte>());
+    if (instance->mem_start) {
+      free(instance->mem_start);
     }
-    if (function_code) delete function_code;
-    if (module) delete module;
+    if (instance->function_code) {
+      delete instance->function_code;
+    }
   }
 
   byte* AddMemory(size_t size) {
-    CHECK_EQ(0, mem_start);
-    CHECK_EQ(0, mem_size);
-    mem_start = reinterpret_cast<uintptr_t>(malloc(size));
-    CHECK(mem_start);
-    byte* raw = raw_mem_start<byte>();
-    memset(raw, 0, size);
-    mem_end = mem_start + size;
-    mem_size = size;
+    CHECK_NULL(instance->mem_start);
+    CHECK_EQ(0, instance->mem_size);
+    instance->mem_start = reinterpret_cast<byte*>(malloc(size));
+    CHECK(instance->mem_start);
+    memset(instance->mem_start, 0, size);
+    instance->mem_size = size;
     return raw_mem_start<byte>();
   }
 
@@ -103,11 +117,10 @@
   template <typename T>
   T* AddGlobal(MachineType mem_type) {
     WasmGlobal* global = AddGlobal(mem_type);
-    return reinterpret_cast<T*>(globals_area + global->offset);
+    return reinterpret_cast<T*>(instance->globals_start + global->offset);
   }
 
   byte AddSignature(FunctionSig* sig) {
-    AllocModule();
     if (!module->signatures) {
       module->signatures = new std::vector<FunctionSig*>();
     }
@@ -119,33 +132,33 @@
 
   template <typename T>
   T* raw_mem_start() {
-    DCHECK(mem_start);
-    return reinterpret_cast<T*>(mem_start);
+    DCHECK(instance->mem_start);
+    return reinterpret_cast<T*>(instance->mem_start);
   }
 
   template <typename T>
   T* raw_mem_end() {
-    DCHECK(mem_end);
-    return reinterpret_cast<T*>(mem_end);
+    DCHECK(instance->mem_start);
+    return reinterpret_cast<T*>(instance->mem_start + instance->mem_size);
   }
 
   template <typename T>
   T raw_mem_at(int i) {
-    DCHECK(mem_start);
-    return reinterpret_cast<T*>(mem_start)[i];
+    DCHECK(instance->mem_start);
+    return reinterpret_cast<T*>(instance->mem_start)[i];
   }
 
   template <typename T>
   T raw_val_at(int i) {
     T val;
-    memcpy(&val, reinterpret_cast<void*>(mem_start + i), sizeof(T));
+    memcpy(&val, reinterpret_cast<void*>(instance->mem_start + i), sizeof(T));
     return val;
   }
 
   // Zero-initialize the memory.
   void BlankMemory() {
     byte* raw = raw_mem_start<byte>();
-    memset(raw, 0, mem_size);
+    memset(raw, 0, instance->mem_size);
   }
 
   // Pseudo-randomly intialize the memory.
@@ -157,26 +170,57 @@
     rng.NextBytes(raw, end - raw);
   }
 
-  WasmFunction* AddFunction(FunctionSig* sig, Handle<Code> code) {
-    AllocModule();
+  int AddFunction(FunctionSig* sig, Handle<Code> code) {
     if (module->functions == nullptr) {
       module->functions = new std::vector<WasmFunction>();
-      function_code = new std::vector<Handle<Code>>();
+      // TODO(titzer): Reserving space here to avoid the underlying WasmFunction
+      // structs from moving.
+      module->functions->reserve(kMaxFunctions);
+      instance->function_code = new std::vector<Handle<Code>>();
     }
-    module->functions->push_back({sig, 0, 0, 0, 0, 0, 0, 0, false, false});
-    function_code->push_back(code);
-    return &module->functions->back();
+    uint32_t index = static_cast<uint32_t>(module->functions->size());
+    module->functions->push_back(
+        {sig, index, 0, 0, 0, 0, 0, 0, 0, false, false});
+    instance->function_code->push_back(code);
+    DCHECK_LT(index, kMaxFunctions);  // limited for testing.
+    return index;
+  }
+
+  void SetFunctionCode(uint32_t index, Handle<Code> code) {
+    instance->function_code->at(index) = code;
+  }
+
+  void AddIndirectFunctionTable(int* functions, int table_size) {
+    Isolate* isolate = module->shared_isolate;
+    Handle<FixedArray> fixed =
+        isolate->factory()->NewFixedArray(2 * table_size);
+    instance->function_table = fixed;
+    module->function_table = new std::vector<uint16_t>();
+    for (int i = 0; i < table_size; i++) {
+      module->function_table->push_back(functions[i]);
+    }
+  }
+
+  void PopulateIndirectFunctionTable() {
+    if (instance->function_table.is_null()) return;
+    int table_size = static_cast<int>(module->function_table->size());
+    for (int i = 0; i < table_size; i++) {
+      int function_index = module->function_table->at(i);
+      WasmFunction* function = &module->functions->at(function_index);
+      instance->function_table->set(i, Smi::FromInt(function->sig_index));
+      instance->function_table->set(
+          i + table_size, *instance->function_code->at(function_index));
+    }
   }
 
  private:
-  size_t mem_size;
+  WasmModule module_;
+  WasmModuleInstance instance_;
   uint32_t global_offset;
-  byte global_data[kMaxGlobalsSize];
+  V8_ALIGNED(8) byte global_data[kMaxGlobalsSize];  // preallocated global data.
 
   WasmGlobal* AddGlobal(MachineType mem_type) {
-    AllocModule();
-    if (globals_area == 0) {
-      globals_area = reinterpret_cast<uintptr_t>(global_data);
+    if (!module->globals) {
       module->globals = new std::vector<WasmGlobal>();
     }
     byte size = WasmOpcodes::MemSize(mem_type);
@@ -187,15 +231,6 @@
     CHECK_LT(global_offset, kMaxGlobalsSize);
     return &module->globals->back();
   }
-  void AllocModule() {
-    if (module == nullptr) {
-      module = new WasmModule();
-      module->shared_isolate = CcTest::InitIsolateOnce();
-      module->globals = nullptr;
-      module->functions = nullptr;
-      module->data_segments = nullptr;
-    }
-  }
 };
 
 
@@ -212,39 +247,212 @@
     str << ", msg = " << result.error_msg.get();
     FATAL(str.str().c_str());
   }
+  builder.Int64LoweringForTesting();
   if (FLAG_trace_turbo_graph) {
     OFStream os(stdout);
     os << AsRPO(*jsgraph->graph());
   }
 }
 
+template <typename ReturnType>
+class WasmFunctionWrapper : public HandleAndZoneScope,
+                            private GraphAndBuilders {
+ public:
+  WasmFunctionWrapper()
+      : GraphAndBuilders(main_zone()),
+        inner_code_node_(nullptr),
+        signature_(nullptr) {
+    // One additional parameter for the pointer to the return value memory.
+    Signature<MachineType>::Builder sig_builder(
+        zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
 
-// A helper for compiling functions that are only internally callable WASM code.
+    sig_builder.AddReturn(MachineType::Int32());
+    for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
+      sig_builder.AddParam(MachineType::Pointer());
+    }
+    signature_ = sig_builder.Build();
+  }
+
+  void Init(CallDescriptor* descriptor, MachineType p0 = MachineType::None(),
+            MachineType p1 = MachineType::None(),
+            MachineType p2 = MachineType::None(),
+            MachineType p3 = MachineType::None()) {
+    // Create the TF graph for the wrapper. The wrapper always takes four
+    // pointers as parameters, but may not pass the values of all pointers to
+    // the actual test function.
+
+    // Function, effect, and control.
+    Node** parameters =
+        zone()->template NewArray<Node*>(WASM_RUNNER_MAX_NUM_PARAMETERS + 3);
+    graph()->SetStart(graph()->NewNode(common()->Start(6)));
+    Node* effect = graph()->start();
+    int parameter_count = 0;
+
+    // Dummy node which gets replaced in SetInnerCode.
+    inner_code_node_ = graph()->NewNode(common()->Int32Constant(0));
+    parameters[parameter_count++] = inner_code_node_;
+
+    if (p0 != MachineType::None()) {
+      parameters[parameter_count] = graph()->NewNode(
+          machine()->Load(p0),
+          graph()->NewNode(common()->Parameter(0), graph()->start()),
+          graph()->NewNode(common()->Int32Constant(0)), effect,
+          graph()->start());
+      effect = parameters[parameter_count++];
+    }
+    if (p1 != MachineType::None()) {
+      parameters[parameter_count] = graph()->NewNode(
+          machine()->Load(p0),
+          graph()->NewNode(common()->Parameter(1), graph()->start()),
+          graph()->NewNode(common()->Int32Constant(0)), effect,
+          graph()->start());
+      effect = parameters[parameter_count++];
+    }
+    if (p2 != MachineType::None()) {
+      parameters[parameter_count] = graph()->NewNode(
+          machine()->Load(p0),
+          graph()->NewNode(common()->Parameter(2), graph()->start()),
+          graph()->NewNode(common()->Int32Constant(0)), effect,
+          graph()->start());
+      effect = parameters[parameter_count++];
+    }
+    if (p3 != MachineType::None()) {
+      parameters[parameter_count] = graph()->NewNode(
+          machine()->Load(p0),
+          graph()->NewNode(common()->Parameter(3), graph()->start()),
+          graph()->NewNode(common()->Int32Constant(0)), effect,
+          graph()->start());
+      effect = parameters[parameter_count++];
+    }
+
+    parameters[parameter_count++] = effect;
+    parameters[parameter_count++] = graph()->start();
+    Node* call = graph()->NewNode(common()->Call(descriptor), parameter_count,
+                                  parameters);
+
+    effect = graph()->NewNode(
+        machine()->Store(
+            StoreRepresentation(MachineTypeForC<ReturnType>().representation(),
+                                WriteBarrierKind::kNoWriteBarrier)),
+        graph()->NewNode(common()->Parameter(WASM_RUNNER_MAX_NUM_PARAMETERS),
+                         graph()->start()),
+        graph()->NewNode(common()->Int32Constant(0)), call, effect,
+        graph()->start());
+    Node* r = graph()->NewNode(
+        common()->Return(),
+        graph()->NewNode(common()->Int32Constant(WASM_WRAPPER_RETURN_VALUE)),
+        effect, graph()->start());
+    graph()->SetEnd(graph()->NewNode(common()->End(2), r, graph()->start()));
+  }
+
+  void SetInnerCode(Handle<Code> code_handle) {
+    NodeProperties::ChangeOp(inner_code_node_,
+                             common()->HeapConstant(code_handle));
+  }
+
+  Handle<Code> GetWrapperCode() {
+    if (code_.is_null()) {
+      Isolate* isolate = CcTest::InitIsolateOnce();
+
+      CallDescriptor* descriptor =
+          Linkage::GetSimplifiedCDescriptor(zone(), signature_, true);
+
+      if (kPointerSize == 4) {
+        // One additional parameter for the pointer of the return value.
+        Signature<MachineRepresentation>::Builder rep_builder(
+            zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
+
+        rep_builder.AddReturn(MachineRepresentation::kWord32);
+        for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
+          rep_builder.AddParam(MachineRepresentation::kWord32);
+        }
+        Int64Lowering r(graph(), machine(), common(), zone(),
+                        rep_builder.Build());
+        r.LowerGraph();
+      }
+
+      CompilationInfo info("testing", isolate, graph()->zone());
+      code_ =
+          Pipeline::GenerateCodeForTesting(&info, descriptor, graph(), nullptr);
+      CHECK(!code_.is_null());
+#ifdef ENABLE_DISASSEMBLER
+      if (FLAG_print_opt_code) {
+        OFStream os(stdout);
+        code_->Disassemble("wasm wrapper", os);
+      }
+#endif
+    }
+
+    return code_;
+  }
+
+  Signature<MachineType>* signature() const { return signature_; }
+
+ private:
+  Node* inner_code_node_;
+  Handle<Code> code_;
+  Signature<MachineType>* signature_;
+};
+
+// 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.
 class WasmFunctionCompiler : public HandleAndZoneScope,
                              private GraphAndBuilders {
  public:
-  explicit WasmFunctionCompiler(FunctionSig* sig, ModuleEnv* module = nullptr)
+  explicit WasmFunctionCompiler(FunctionSig* sig, TestingModule* module)
       : GraphAndBuilders(main_zone()),
         jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
                 nullptr, this->machine()),
-        descriptor_(nullptr) {
+        descriptor_(nullptr),
+        testing_module_(module) {
     init_env(&env, sig);
     env.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;
+    }
+  }
+
+  ~WasmFunctionCompiler() {
+    if (function_) delete function_;
   }
 
   JSGraph jsgraph;
   FunctionEnv env;
   // The call descriptor is initialized when the function is compiled.
   CallDescriptor* descriptor_;
+  TestingModule* testing_module_;
+  WasmFunction* function_;
+  int function_index_;
 
   Isolate* isolate() { return main_isolate(); }
   Graph* graph() const { return main_graph_; }
   Zone* zone() const { return graph()->zone(); }
   CommonOperatorBuilder* common() { return &main_common_; }
   MachineOperatorBuilder* machine() { return &main_machine_; }
+  void InitializeDescriptor() {
+    if (descriptor_ == nullptr) {
+      descriptor_ = env.module->GetWasmCallDescriptor(main_zone(), env.sig);
+    }
+  }
   CallDescriptor* descriptor() { return descriptor_; }
 
   void Build(const byte* start, const byte* end) {
+    // Transfer local counts before compiling.
+    function()->local_i32_count = env.local_i32_count;
+    function()->local_i64_count = env.local_i64_count;
+    function()->local_f32_count = env.local_f32_count;
+    function()->local_f64_count = env.local_f64_count;
+
+    // Build the TurboFan graph.
     TestBuildingGraph(main_zone(), &jsgraph, &env, start, end);
   }
 
@@ -256,11 +464,16 @@
     return b;
   }
 
-  Handle<Code> Compile(ModuleEnv* module) {
-    descriptor_ = module->GetWasmCallDescriptor(this->zone(), env.sig);
+  // TODO(titzer): remove me.
+  Handle<Code> Compile() {
+    InitializeDescriptor();
+    CallDescriptor* desc = descriptor_;
+    if (kPointerSize == 4) {
+      desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
+    }
     CompilationInfo info("wasm compile", this->isolate(), this->zone());
     Handle<Code> result =
-        Pipeline::GenerateCodeForTesting(&info, descriptor_, this->graph());
+        Pipeline::GenerateCodeForTesting(&info, desc, this->graph());
 #ifdef ENABLE_DISASSEMBLER
     if (!result.is_null() && FLAG_print_opt_code) {
       OFStream os(stdout);
@@ -271,17 +484,21 @@
     return result;
   }
 
-  uint32_t CompileAndAdd(TestingModule* module) {
-    uint32_t index = 0;
-    if (module->module && module->module->functions) {
-      index = static_cast<uint32_t>(module->module->functions->size());
-    }
-    module->AddFunction(env.sig, Compile(module));
-    return index;
+  // TODO(titzer): remove me.
+  uint32_t CompileAndAdd(uint16_t sig_index = 0) {
+    CHECK(testing_module_);
+    function()->sig_index = sig_index;
+    Handle<Code> code = Compile();
+    testing_module_->SetFunctionCode(function_index_, code);
+    return static_cast<uint32_t>(function_index_);
+  }
+
+  WasmFunction* function() {
+    if (function_) return function_;
+    return &testing_module_->module->functions->at(function_index_);
   }
 };
 
-
 // A helper class to build graphs from Wasm bytecode, generate machine
 // code, and run that code.
 template <typename ReturnType>
@@ -291,11 +508,28 @@
              MachineType p1 = MachineType::None(),
              MachineType p2 = MachineType::None(),
              MachineType p3 = MachineType::None())
-      : signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
+      : compiled_(false),
+
+        signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
                    GetParameterCount(p0, p1, p2, p3), storage_),
-        compiler_(&signature_),
-        call_wrapper_(p0, p1, p2, p3),
-        compilation_done_(false) {
+        compiler_(&signature_, nullptr) {
+    InitSigStorage(p0, p1, p2, p3);
+  }
+
+  WasmRunner(TestingModule* module, MachineType p0 = MachineType::None(),
+             MachineType p1 = MachineType::None(),
+             MachineType p2 = MachineType::None(),
+             MachineType p3 = MachineType::None())
+      : compiled_(false),
+        signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
+                   GetParameterCount(p0, p1, p2, p3), storage_),
+        compiler_(&signature_, module) {
+    DCHECK(module);
+    InitSigStorage(p0, p1, p2, p3);
+  }
+
+  void InitSigStorage(MachineType p0, MachineType p1, MachineType p2,
+                      MachineType p3) {
     int index = 0;
     MachineType ret = MachineTypeForC<ReturnType>();
     if (ret != MachineType::None()) {
@@ -309,56 +543,60 @@
       storage_[index++] = WasmOpcodes::LocalTypeFor(p2);
     if (p3 != MachineType::None())
       storage_[index++] = WasmOpcodes::LocalTypeFor(p3);
-  }
 
+    compiler_.InitializeDescriptor();
+    wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3);
+  }
 
   FunctionEnv* env() { return &compiler_.env; }
 
-
-  // Builds a graph from the given Wasm code, and generates the machine
+  // Builds a graph from the given Wasm code and generates the machine
   // code and call wrapper for that graph. This method must not be called
   // more than once.
   void Build(const byte* start, const byte* end) {
-    DCHECK(!compilation_done_);
-    compilation_done_ = true;
-    // Build the TF graph.
+    CHECK(!compiled_);
+    compiled_ = true;
+
+    // Build the TF graph within the compiler.
     compiler_.Build(start, end);
     // Generate code.
-    Handle<Code> code = compiler_.Compile(env()->module);
+    Handle<Code> code = compiler_.Compile();
 
-    // Construct the call wrapper.
-    Node* inputs[5];
-    int input_count = 0;
-    inputs[input_count++] = call_wrapper_.HeapConstant(code);
-    for (size_t i = 0; i < signature_.parameter_count(); i++) {
-      inputs[input_count++] = call_wrapper_.Parameter(i);
+    if (compiler_.testing_module_) {
+      // Update the table of function code in the module.
+      compiler_.testing_module_->SetFunctionCode(compiler_.function_index_,
+                                                 code);
     }
 
-    call_wrapper_.Return(call_wrapper_.AddNode(
-        call_wrapper_.common()->Call(compiler_.descriptor()), input_count,
-        inputs));
+    wrapper_.SetInnerCode(code);
   }
 
-  ReturnType Call() { return call_wrapper_.Call(); }
+  ReturnType Call() { return Call(0, 0, 0, 0); }
 
   template <typename P0>
   ReturnType Call(P0 p0) {
-    return call_wrapper_.Call(p0);
+    return Call(p0, 0, 0, 0);
   }
 
   template <typename P0, typename P1>
   ReturnType Call(P0 p0, P1 p1) {
-    return call_wrapper_.Call(p0, p1);
+    return Call(p0, p1, 0, 0);
   }
 
   template <typename P0, typename P1, typename P2>
   ReturnType Call(P0 p0, P1 p1, P2 p2) {
-    return call_wrapper_.Call(p0, p1, p2);
+    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) {
-    return call_wrapper_.Call(p0, p1, p2, 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;
   }
 
   byte AllocateLocal(LocalType type) {
@@ -369,12 +607,13 @@
     return b;
   }
 
- private:
-  LocalType storage_[5];
+ protected:
+  Zone zone;
+  bool compiled_;
+  LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS];
   FunctionSig signature_;
   WasmFunctionCompiler compiler_;
-  BufferedRawMachineAssemblerTester<ReturnType> call_wrapper_;
-  bool compilation_done_;
+  WasmFunctionWrapper<ReturnType> wrapper_;
 
   static size_t GetParameterCount(MachineType p0, MachineType p1,
                                   MachineType p2, MachineType p3) {
diff --git a/test/default.gyp b/test/default.gyp
index 53a8d7d..efc0406 100644
--- a/test/default.gyp
+++ b/test/default.gyp
@@ -11,6 +11,7 @@
           'type': 'none',
           'dependencies': [
             'cctest/cctest.gyp:cctest_run',
+            'fuzzer/fuzzer.gyp:fuzzer_run',
             'intl/intl.gyp:intl_run',
             'message/message.gyp:message_run',
             'mjsunit/mjsunit.gyp:mjsunit_run',
diff --git a/test/default.isolate b/test/default.isolate
index 68044cf..416137c 100644
--- a/test/default.isolate
+++ b/test/default.isolate
@@ -2,8 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 {
+  'variables': {
+    'command': [
+      '../tools/run-tests.py',
+    ],
+  },
   'includes': [
     'cctest/cctest.isolate',
+    'fuzzer/fuzzer.isolate',
     'intl/intl.isolate',
     'message/message.isolate',
     'mjsunit/mjsunit.isolate',
diff --git a/test/fuzzer/DEPS b/test/fuzzer/DEPS
new file mode 100644
index 0000000..3e73aa2
--- /dev/null
+++ b/test/fuzzer/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+src",
+]
diff --git a/test/fuzzer/fuzzer-support.cc b/test/fuzzer/fuzzer-support.cc
new file mode 100644
index 0000000..cf3ee8c
--- /dev/null
+++ b/test/fuzzer/fuzzer-support.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 "test/fuzzer/fuzzer-support.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "include/libplatform/libplatform.h"
+
+namespace v8_fuzzer {
+
+namespace {
+
+FuzzerSupport* g_fuzzer_support = nullptr;
+
+void DeleteFuzzerSupport() {
+  if (g_fuzzer_support) {
+    delete g_fuzzer_support;
+    g_fuzzer_support = nullptr;
+  }
+}
+
+}  // namespace
+
+class FuzzerSupport::ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
+ public:
+  virtual void* Allocate(size_t length) {
+    void* data = AllocateUninitialized(length);
+    return data == NULL ? data : memset(data, 0, length);
+  }
+  virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
+  virtual void Free(void* data, size_t) { free(data); }
+};
+
+FuzzerSupport::FuzzerSupport(int* argc, char*** argv) {
+  v8::V8::SetFlagsFromCommandLine(argc, *argv, true);
+  v8::V8::InitializeICU();
+  v8::V8::InitializeExternalStartupData((*argv)[0]);
+  platform_ = v8::platform::CreateDefaultPlatform();
+  v8::V8::InitializePlatform(platform_);
+  v8::V8::Initialize();
+
+  allocator_ = new ArrayBufferAllocator;
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = allocator_;
+  isolate_ = v8::Isolate::New(create_params);
+
+  {
+    v8::Isolate::Scope isolate_scope(isolate_);
+    v8::HandleScope handle_scope(isolate_);
+    context_.Reset(isolate_, v8::Context::New(isolate_));
+  }
+}
+
+FuzzerSupport::~FuzzerSupport() {
+  {
+    v8::Isolate::Scope isolate_scope(isolate_);
+    while (v8::platform::PumpMessageLoop(platform_, isolate_)) /* empty */
+      ;
+
+    v8::HandleScope handle_scope(isolate_);
+    context_.Reset();
+  }
+
+  isolate_->Dispose();
+  isolate_ = nullptr;
+
+  delete allocator_;
+  allocator_ = nullptr;
+
+  v8::V8::Dispose();
+  v8::V8::ShutdownPlatform();
+
+  delete platform_;
+  platform_ = nullptr;
+}
+
+// static
+FuzzerSupport* FuzzerSupport::Get() { return g_fuzzer_support; }
+
+v8::Isolate* FuzzerSupport::GetIsolate() { return isolate_; }
+
+v8::Local<v8::Context> FuzzerSupport::GetContext() {
+  v8::Isolate::Scope isolate_scope(isolate_);
+  v8::EscapableHandleScope handle_scope(isolate_);
+  v8::Local<v8::Context> context =
+      v8::Local<v8::Context>::New(isolate_, context_);
+  return handle_scope.Escape(context);
+}
+
+}  // namespace v8_fuzzer
+
+extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
+  v8_fuzzer::g_fuzzer_support = new v8_fuzzer::FuzzerSupport(argc, argv);
+  atexit(&v8_fuzzer::DeleteFuzzerSupport);
+  return 0;
+}
diff --git a/test/fuzzer/fuzzer-support.h b/test/fuzzer/fuzzer-support.h
new file mode 100644
index 0000000..0241c53
--- /dev/null
+++ b/test/fuzzer/fuzzer-support.h
@@ -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.
+
+#ifndef TEST_FUZZER_FUZZER_SUPPORT_H_
+#define TEST_FUZZER_FUZZER_SUPPORT_H_
+
+#include "include/v8.h"
+
+namespace v8_fuzzer {
+
+class FuzzerSupport {
+ public:
+  FuzzerSupport(int* argc, char*** argv);
+  ~FuzzerSupport();
+
+  static FuzzerSupport* Get();
+
+  v8::Isolate* GetIsolate();
+  v8::Local<v8::Context> GetContext();
+
+ private:
+  // Prevent copying. Not implemented.
+  FuzzerSupport(const FuzzerSupport&);
+  FuzzerSupport& operator=(const FuzzerSupport&);
+
+  class ArrayBufferAllocator;
+
+  v8::Platform* platform_;
+  ArrayBufferAllocator* allocator_;
+  v8::Isolate* isolate_;
+  v8::Global<v8::Context> context_;
+};
+
+}  // namespace
+
+#endif  //  TEST_FUZZER_FUZZER_SUPPORT_H_
diff --git a/test/fuzzer/fuzzer.cc b/test/fuzzer/fuzzer.cc
new file mode 100644
index 0000000..71a26b8
--- /dev/null
+++ b/test/fuzzer/fuzzer.cc
@@ -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.
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv);
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
+
+int main(int argc, char* argv[]) {
+  if (LLVMFuzzerInitialize(&argc, &argv)) {
+    fprintf(stderr, "Failed to initialize fuzzer target\n");
+    return 1;
+  }
+
+  if (argc < 2) {
+    fprintf(stderr, "USAGE: %s <input>\n", argv[0]);
+    return 1;
+  }
+
+  FILE* input = fopen(argv[1], "rb");
+
+  if (!input) {
+    fprintf(stderr, "Failed to open '%s'\n", argv[1]);
+    return 1;
+  }
+
+  fseek(input, 0, SEEK_END);
+  long size = ftell(input);
+  fseek(input, 0, SEEK_SET);
+
+  uint8_t* data = reinterpret_cast<uint8_t*>(malloc(size));
+  if (!data) {
+    fclose(input);
+    fprintf(stderr, "Failed to allocate %ld bytes\n", size);
+    return 1;
+  }
+
+  size_t bytes_read = fread(data, 1, size, input);
+  fclose(input);
+
+  if (bytes_read != size) {
+    free(data);
+    fprintf(stderr, "Failed to read %s\n", argv[1]);
+    return 1;
+  }
+
+  int result = LLVMFuzzerTestOneInput(data, size);
+
+  free(data);
+
+  return result;
+}
diff --git a/test/fuzzer/fuzzer.gyp b/test/fuzzer/fuzzer.gyp
new file mode 100644
index 0000000..5fc338c
--- /dev/null
+++ b/test/fuzzer/fuzzer.gyp
@@ -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.
+
+{
+  'variables': {
+    'v8_code': 1,
+  },
+  'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'],
+  'targets': [
+    {
+      'target_name': 'json_fuzzer',
+      'type': 'executable',
+      'dependencies': [
+        'json_fuzzer_lib',
+      ],
+      'include_dirs': [
+        '../..',
+      ],
+      'sources': [
+        'fuzzer.cc',
+      ],
+    },
+    {
+      'target_name': 'json_fuzzer_lib',
+      'type': 'static_library',
+      'dependencies': [
+        'fuzzer_support',
+      ],
+      'include_dirs': [
+        '../..',
+      ],
+      'sources': [  ### gcmole(all) ###
+        'json.cc',
+      ],
+    },
+    {
+      'target_name': 'parser_fuzzer',
+      'type': 'executable',
+      'dependencies': [
+        'parser_fuzzer_lib',
+      ],
+      'include_dirs': [
+        '../..',
+      ],
+      'sources': [
+        'fuzzer.cc',
+      ],
+    },
+    {
+      'target_name': 'parser_fuzzer_lib',
+      'type': 'static_library',
+      'dependencies': [
+        'fuzzer_support',
+      ],
+      'include_dirs': [
+        '../..',
+      ],
+      'sources': [  ### gcmole(all) ###
+        'parser.cc',
+      ],
+    },
+    {
+      'target_name': 'regexp_fuzzer',
+      'type': 'executable',
+      'dependencies': [
+        'regexp_fuzzer_lib',
+      ],
+      'include_dirs': [
+        '../..',
+      ],
+      'sources': [
+        'fuzzer.cc',
+      ],
+    },
+    {
+      'target_name': 'regexp_fuzzer_lib',
+      'type': 'static_library',
+      'dependencies': [
+        'fuzzer_support',
+      ],
+      'include_dirs': [
+        '../..',
+      ],
+      'sources': [  ### gcmole(all) ###
+        'regexp.cc',
+      ],
+    },
+    {
+      'target_name': 'fuzzer_support',
+      'type': 'static_library',
+      'dependencies': [
+        '../../tools/gyp/v8.gyp:v8_libplatform',
+      ],
+      'include_dirs': [
+        '../..',
+      ],
+      'sources': [  ### gcmole(all) ###
+        'fuzzer-support.cc',
+        'fuzzer-support.h',
+      ],
+      'conditions': [
+        ['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': ['../../tools/gyp/v8.gyp:v8'],
+        }],
+      ],
+    },
+  ],
+  'conditions': [
+    ['test_isolation_mode != "noop"', {
+      'targets': [
+        {
+          'target_name': 'fuzzer_run',
+          'type': 'none',
+          'dependencies': [
+            'json_fuzzer',
+            'parser_fuzzer',
+            'regexp_fuzzer',
+          ],
+          'includes': [
+            '../../build/isolate.gypi',
+          ],
+          'sources': [
+            'fuzzer.isolate',
+          ],
+        },
+      ],
+    }],
+  ],
+}
diff --git a/test/fuzzer/fuzzer.isolate b/test/fuzzer/fuzzer.isolate
new file mode 100644
index 0000000..286be2f
--- /dev/null
+++ b/test/fuzzer/fuzzer.isolate
@@ -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.
+
+{
+  'variables': {
+    'files': [
+      '<(PRODUCT_DIR)/json_fuzzer<(EXECUTABLE_SUFFIX)',
+      '<(PRODUCT_DIR)/parser_fuzzer<(EXECUTABLE_SUFFIX)',
+      '<(PRODUCT_DIR)/regexp_fuzzer<(EXECUTABLE_SUFFIX)',
+      './fuzzer.status',
+      './testcfg.py',
+      './json/',
+      './parser/',
+      './regexp/',
+    ],
+  },
+  'includes': [
+    '../../src/base.isolate',
+    '../../tools/testrunner/testrunner.isolate',
+  ],
+}
diff --git a/test/fuzzer/fuzzer.status b/test/fuzzer/fuzzer.status
new file mode 100644
index 0000000..df922bb
--- /dev/null
+++ b/test/fuzzer/fuzzer.status
@@ -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.
+
+[
+
+]
diff --git a/test/fuzzer/json.cc b/test/fuzzer/json.cc
new file mode 100644
index 0000000..f20e9b9
--- /dev/null
+++ b/test/fuzzer/json.cc
@@ -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.
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "include/v8.h"
+#include "test/fuzzer/fuzzer-support.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  v8_fuzzer::FuzzerSupport* support = v8_fuzzer::FuzzerSupport::Get();
+  v8::Isolate* isolate = support->GetIsolate();
+
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::HandleScope handle_scope(isolate);
+  v8::Context::Scope context_scope(support->GetContext());
+  v8::TryCatch try_catch(isolate);
+
+  if (size > INT_MAX) return 0;
+  v8::Local<v8::String> source;
+  if (!v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
+                                  static_cast<int>(size))
+           .ToLocal(&source)) {
+    return 0;
+  }
+
+  v8::JSON::Parse(isolate, source).IsEmpty();
+  return 0;
+}
diff --git a/test/fuzzer/json/json b/test/fuzzer/json/json
new file mode 100644
index 0000000..f3400b3
--- /dev/null
+++ b/test/fuzzer/json/json
@@ -0,0 +1 @@
+{"json": 1}
diff --git a/test/fuzzer/json/not-json b/test/fuzzer/json/not-json
new file mode 100644
index 0000000..6b7a9f4
--- /dev/null
+++ b/test/fuzzer/json/not-json
@@ -0,0 +1 @@
+not json
diff --git a/test/fuzzer/parser.cc b/test/fuzzer/parser.cc
new file mode 100644
index 0000000..aee4c0d
--- /dev/null
+++ b/test/fuzzer/parser.cc
@@ -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.
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "include/v8.h"
+#include "src/objects.h"
+#include "src/parsing/parser.h"
+#include "src/parsing/preparser.h"
+#include "test/fuzzer/fuzzer-support.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  v8_fuzzer::FuzzerSupport* support = v8_fuzzer::FuzzerSupport::Get();
+  v8::Isolate* isolate = support->GetIsolate();
+
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::HandleScope handle_scope(isolate);
+  v8::Context::Scope context_scope(support->GetContext());
+  v8::TryCatch try_catch(isolate);
+
+  v8::internal::Isolate* i_isolate =
+      reinterpret_cast<v8::internal::Isolate*>(isolate);
+  v8::internal::Factory* factory = i_isolate->factory();
+
+  if (size > INT_MAX) return 0;
+  v8::internal::MaybeHandle<v8::internal::String> source =
+      factory->NewStringFromOneByte(
+          v8::internal::Vector<const uint8_t>(data, static_cast<int>(size)));
+  if (source.is_null()) return 0;
+
+  v8::internal::Handle<v8::internal::Script> script =
+      factory->NewScript(source.ToHandleChecked());
+  v8::internal::Zone zone;
+  v8::internal::ParseInfo info(&zone, script);
+  info.set_global();
+  v8::internal::Parser parser(&info);
+  parser.Parse(&info);
+  return 0;
+}
diff --git a/test/fuzzer/parser/hello-world b/test/fuzzer/parser/hello-world
new file mode 100644
index 0000000..6be0237
--- /dev/null
+++ b/test/fuzzer/parser/hello-world
@@ -0,0 +1 @@
+console.log('hello world');
diff --git a/test/fuzzer/regexp.cc b/test/fuzzer/regexp.cc
new file mode 100644
index 0000000..eb51da8
--- /dev/null
+++ b/test/fuzzer/regexp.cc
@@ -0,0 +1,75 @@
+// Copyright 2016 the V8 project 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 <stddef.h>
+#include <stdint.h>
+
+#include "include/v8.h"
+#include "src/factory.h"
+#include "src/objects-inl.h"
+#include "src/objects.h"
+#include "src/regexp/jsregexp.h"
+#include "test/fuzzer/fuzzer-support.h"
+
+namespace i = v8::internal;
+
+void Test(v8::Isolate* isolate, i::Handle<i::JSRegExp> regexp,
+          i::Handle<i::String> subject, i::Handle<i::JSArray> results_array) {
+  v8::TryCatch try_catch(isolate);
+  USE(i::RegExpImpl::Exec(regexp, subject, 0, results_array));
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  v8_fuzzer::FuzzerSupport* support = v8_fuzzer::FuzzerSupport::Get();
+  v8::Isolate* isolate = support->GetIsolate();
+
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::HandleScope handle_scope(isolate);
+  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);
+  i::Factory* factory = i_isolate->factory();
+
+  if (size > INT_MAX) return 0;
+  i::MaybeHandle<i::String> maybe_source = factory->NewStringFromOneByte(
+      i::Vector<const uint8_t>(data, static_cast<int>(size)));
+  i::Handle<i::String> source;
+  if (!maybe_source.ToHandle(&source)) return 0;
+
+  static const int kAllFlags = i::JSRegExp::kGlobal | i::JSRegExp::kIgnoreCase |
+                               i::JSRegExp::kMultiline | i::JSRegExp::kSticky |
+                               i::JSRegExp::kUnicode;
+
+  const uint8_t one_byte_array[6] = {'f', 'o', 'o', 'b', 'a', 'r'};
+  const i::uc16 two_byte_array[6] = {'f', 0xD83D, 0xDCA9, 'b', 'a', 0x2603};
+
+  i::Handle<i::JSArray> results_array = factory->NewJSArray(5);
+  i::Handle<i::String> one_byte =
+      factory->NewStringFromOneByte(i::Vector<const uint8_t>(one_byte_array, 6))
+          .ToHandleChecked();
+  i::Handle<i::String> two_byte =
+      factory->NewStringFromTwoByte(i::Vector<const i::uc16>(two_byte_array, 6))
+          .ToHandleChecked();
+
+  for (int flags = 0; flags <= kAllFlags; flags++) {
+    i::Handle<i::JSRegExp> regexp;
+    {
+      v8::TryCatch try_catch(isolate);
+      i::MaybeHandle<i::JSRegExp> maybe_regexp =
+          i::JSRegExp::New(source, static_cast<i::JSRegExp::Flags>(flags));
+      if (!maybe_regexp.ToHandle(&regexp)) continue;
+    }
+    Test(isolate, regexp, one_byte, results_array);
+    Test(isolate, regexp, two_byte, results_array);
+    Test(isolate, regexp, factory->empty_string(), results_array);
+    Test(isolate, regexp, source, results_array);
+  }
+
+  return 0;
+}
diff --git a/test/fuzzer/regexp/test00 b/test/fuzzer/regexp/test00
new file mode 100644
index 0000000..d2a71ae
--- /dev/null
+++ b/test/fuzzer/regexp/test00
@@ -0,0 +1 @@
+a*
diff --git a/test/fuzzer/regexp/test01 b/test/fuzzer/regexp/test01
new file mode 100644
index 0000000..83877e9
--- /dev/null
+++ b/test/fuzzer/regexp/test01
@@ -0,0 +1 @@
+xyz{93}?
diff --git a/test/fuzzer/regexp/test02 b/test/fuzzer/regexp/test02
new file mode 100644
index 0000000..d27d2ce
--- /dev/null
+++ b/test/fuzzer/regexp/test02
@@ -0,0 +1 @@
+(foo|bar|baz)
diff --git a/test/fuzzer/regexp/test03 b/test/fuzzer/regexp/test03
new file mode 100644
index 0000000..da14770
--- /dev/null
+++ b/test/fuzzer/regexp/test03
@@ -0,0 +1 @@
+[^]
diff --git a/test/fuzzer/regexp/test04 b/test/fuzzer/regexp/test04
new file mode 100644
index 0000000..a672b26
--- /dev/null
+++ b/test/fuzzer/regexp/test04
@@ -0,0 +1 @@
+[\d]
diff --git a/test/fuzzer/regexp/test05 b/test/fuzzer/regexp/test05
new file mode 100644
index 0000000..edcff4e
--- /dev/null
+++ b/test/fuzzer/regexp/test05
@@ -0,0 +1 @@
+\c1
diff --git a/test/fuzzer/regexp/test06 b/test/fuzzer/regexp/test06
new file mode 100644
index 0000000..74c75c6
--- /dev/null
+++ b/test/fuzzer/regexp/test06
@@ -0,0 +1 @@
+[a\]c]
diff --git a/test/fuzzer/regexp/test07 b/test/fuzzer/regexp/test07
new file mode 100644
index 0000000..2ed8704
--- /dev/null
+++ b/test/fuzzer/regexp/test07
@@ -0,0 +1 @@
+\00011
diff --git a/test/fuzzer/regexp/test08 b/test/fuzzer/regexp/test08
new file mode 100644
index 0000000..62d553c
--- /dev/null
+++ b/test/fuzzer/regexp/test08
@@ -0,0 +1 @@
+(x)(x)(x)\2*
diff --git a/test/fuzzer/regexp/test09 b/test/fuzzer/regexp/test09
new file mode 100644
index 0000000..2916500
--- /dev/null
+++ b/test/fuzzer/regexp/test09
@@ -0,0 +1 @@
+(?=a)?a
diff --git a/test/fuzzer/regexp/test10 b/test/fuzzer/regexp/test10
new file mode 100644
index 0000000..8aac695
--- /dev/null
+++ b/test/fuzzer/regexp/test10
@@ -0,0 +1 @@
+\1\2(a(?<=\1(b\1\2))\2)\1
diff --git a/test/fuzzer/regexp/test11 b/test/fuzzer/regexp/test11
new file mode 100644
index 0000000..f9101ec
--- /dev/null
+++ b/test/fuzzer/regexp/test11
@@ -0,0 +1 @@
+\x34
diff --git a/test/fuzzer/regexp/test12 b/test/fuzzer/regexp/test12
new file mode 100644
index 0000000..c418bbd
--- /dev/null
+++ b/test/fuzzer/regexp/test12
@@ -0,0 +1 @@
+\u{12345}|\u{23456}
diff --git a/test/fuzzer/regexp/test13 b/test/fuzzer/regexp/test13
new file mode 100644
index 0000000..6e50a55
--- /dev/null
+++ b/test/fuzzer/regexp/test13
@@ -0,0 +1 @@
+^a
diff --git a/test/fuzzer/regexp/test14 b/test/fuzzer/regexp/test14
new file mode 100644
index 0000000..5020b3b
--- /dev/null
+++ b/test/fuzzer/regexp/test14
@@ -0,0 +1 @@
+a{1,1}?
diff --git a/test/fuzzer/regexp/test15 b/test/fuzzer/regexp/test15
new file mode 100644
index 0000000..d1c4bde
--- /dev/null
+++ b/test/fuzzer/regexp/test15
@@ -0,0 +1 @@
+a\d
diff --git a/test/fuzzer/regexp/test16 b/test/fuzzer/regexp/test16
new file mode 100644
index 0000000..c2d990e
--- /dev/null
+++ b/test/fuzzer/regexp/test16
@@ -0,0 +1 @@
+a[\q]
diff --git a/test/fuzzer/regexp/test17 b/test/fuzzer/regexp/test17
new file mode 100644
index 0000000..d62fa9d
--- /dev/null
+++ b/test/fuzzer/regexp/test17
@@ -0,0 +1 @@
+\0
diff --git a/test/fuzzer/regexp/test18 b/test/fuzzer/regexp/test18
new file mode 100644
index 0000000..3836c6f
--- /dev/null
+++ b/test/fuzzer/regexp/test18
@@ -0,0 +1 @@
+a{1z}
diff --git a/test/fuzzer/regexp/test19 b/test/fuzzer/regexp/test19
new file mode 100644
index 0000000..7eafbfd
--- /dev/null
+++ b/test/fuzzer/regexp/test19
@@ -0,0 +1 @@
+{12z}
diff --git a/test/fuzzer/regexp/test20 b/test/fuzzer/regexp/test20
new file mode 100644
index 0000000..948cf94
--- /dev/null
+++ b/test/fuzzer/regexp/test20
@@ -0,0 +1 @@
+|
diff --git a/test/fuzzer/regexp/test21 b/test/fuzzer/regexp/test21
new file mode 100644
index 0000000..5d2207b
--- /dev/null
+++ b/test/fuzzer/regexp/test21
@@ -0,0 +1 @@
+(?:ab)*
diff --git a/test/fuzzer/regexp/test22 b/test/fuzzer/regexp/test22
new file mode 100644
index 0000000..2ca0499
--- /dev/null
+++ b/test/fuzzer/regexp/test22
@@ -0,0 +1 @@
+(?:a*)?
diff --git a/test/fuzzer/regexp/test23 b/test/fuzzer/regexp/test23
new file mode 100644
index 0000000..fbe9c0c
--- /dev/null
+++ b/test/fuzzer/regexp/test23
@@ -0,0 +1 @@
+(?:a+){0}
diff --git a/test/fuzzer/regexp/test24 b/test/fuzzer/regexp/test24
new file mode 100644
index 0000000..bc09447
--- /dev/null
+++ b/test/fuzzer/regexp/test24
@@ -0,0 +1 @@
+a\Bc
diff --git a/test/fuzzer/testcfg.py b/test/fuzzer/testcfg.py
new file mode 100644
index 0000000..976325a
--- /dev/null
+++ b/test/fuzzer/testcfg.py
@@ -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.
+
+import os
+
+from testrunner.local import testsuite
+from testrunner.objects import testcase
+
+
+class FuzzerVariantGenerator(testsuite.VariantGenerator):
+  # Only run the fuzzer with standard variant.
+  def FilterVariantsByTest(self, testcase):
+    return self.standard_variant
+
+  def GetFlagSets(self, testcase, variant):
+    return testsuite.FAST_VARIANT_FLAGS[variant]
+
+
+class FuzzerTestSuite(testsuite.TestSuite):
+  SUB_TESTS = ( 'json', 'parser', 'regexp', )
+
+  def __init__(self, name, root):
+    super(FuzzerTestSuite, self).__init__(name, root)
+
+  def ListTests(self, context):
+    tests = []
+    for subtest in FuzzerTestSuite.SUB_TESTS:
+      shell = '%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
+        test = testcase.TestCase(self, '%s/%s' % (subtest, fname),
+                                 override_shell=shell)
+        tests.append(test)
+    tests.sort()
+    return tests
+
+  def GetFlagsForTestCase(self, testcase, context):
+    suite, name = testcase.path.split('/')
+    return [os.path.join(self.root, suite, name)]
+
+  def _VariantGeneratorFactory(self):
+    return FuzzerVariantGenerator
+
+
+def GetSuite(name, root):
+  return FuzzerTestSuite(name, root)
diff --git a/test/ignition.isolate b/test/ignition.isolate
index 9604a69..7e4e581 100644
--- a/test/ignition.isolate
+++ b/test/ignition.isolate
@@ -2,6 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 {
+  'variables': {
+    'command': [
+      '../tools/run-tests.py',
+    ],
+  },
   'includes': [
     'cctest/cctest.isolate',
     'mjsunit/mjsunit.isolate',
diff --git a/test/message/arrow-invalid-rest-2.js b/test/message/arrow-invalid-rest-2.js
new file mode 100644
index 0000000..3517803
--- /dev/null
+++ b/test/message/arrow-invalid-rest-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 f = (a, ...x = 10) => x;
+f(1, 2, 3, 4, 5);
diff --git a/test/message/arrow-invalid-rest-2.out b/test/message/arrow-invalid-rest-2.out
new file mode 100644
index 0000000..0196483
--- /dev/null
+++ b/test/message/arrow-invalid-rest-2.out
@@ -0,0 +1,4 @@
+*%(basename)s:7: SyntaxError: Rest parameter must be an identifier or destructuring pattern
+var f = (a, ...x = 10) => x;
+            ^^^^^^^^^
+SyntaxError: Rest parameter must be an identifier or destructuring pattern
diff --git a/test/message/arrow-invalid-rest.js b/test/message/arrow-invalid-rest.js
new file mode 100644
index 0000000..870dbe9
--- /dev/null
+++ b/test/message/arrow-invalid-rest.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 f = (...x = 10) => x;
+f(1, 2, 3, 4, 5);
diff --git a/test/message/arrow-invalid-rest.out b/test/message/arrow-invalid-rest.out
new file mode 100644
index 0000000..4045f14
--- /dev/null
+++ b/test/message/arrow-invalid-rest.out
@@ -0,0 +1,4 @@
+*%(basename)s:7: SyntaxError: Rest parameter must be an identifier or destructuring pattern
+var f = (...x = 10) => x;
+         ^^^^^^^^^
+SyntaxError: Rest parameter must be an identifier or destructuring pattern
diff --git a/test/message/function-sent-escaped.js b/test/message/function-sent-escaped.js
new file mode 100644
index 0000000..aa17258
--- /dev/null
+++ b/test/message/function-sent-escaped.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-function-sent
+
+function* f() {
+  return function.s\u0065nt;
+}
+for (var i of f()) print(i);
diff --git a/test/message/function-sent-escaped.out b/test/message/function-sent-escaped.out
new file mode 100644
index 0000000..d9613d8
--- /dev/null
+++ b/test/message/function-sent-escaped.out
@@ -0,0 +1,4 @@
+*%(basename)s:8: SyntaxError: 'function.sent' must not contain escaped characters
+  return function.s\u0065nt;
+         ^^^^^^^^^^^^^^^^^^
+SyntaxError: 'function.sent' must not contain escaped characters
diff --git a/test/message/new-target-escaped.js b/test/message/new-target-escaped.js
new file mode 100644
index 0000000..f8398be
--- /dev/null
+++ b/test/message/new-target-escaped.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 f() {
+  return new.t\u0061rget;
+}
+var o = new f();
diff --git a/test/message/new-target-escaped.out b/test/message/new-target-escaped.out
new file mode 100644
index 0000000..21b30e3
--- /dev/null
+++ b/test/message/new-target-escaped.out
@@ -0,0 +1,4 @@
+*%(basename)s:8: SyntaxError: 'new.target' must not contain escaped characters
+  return new.t\u0061rget;
+         ^^^^^^^^^^^^^^^
+SyntaxError: 'new.target' must not contain escaped characters
diff --git a/test/message/try-catch-lexical-conflict.out b/test/message/try-catch-lexical-conflict.out
index 9dc1b54..0a7a0eb 100644
--- a/test/message/try-catch-lexical-conflict.out
+++ b/test/message/try-catch-lexical-conflict.out
@@ -1,4 +1,4 @@
 *%(basename)s:10: SyntaxError: Identifier 'x' has already been declared
   let x;
-       ^
+      ^
 SyntaxError: Identifier 'x' has already been declared
diff --git a/test/message/try-catch-variable-conflict.out b/test/message/try-catch-variable-conflict.out
index c7fb8de..be4858e 100644
--- a/test/message/try-catch-variable-conflict.out
+++ b/test/message/try-catch-variable-conflict.out
@@ -1,4 +1,4 @@
 *%(basename)s:9: SyntaxError: Identifier 'x' has already been declared
   var x;
-       ^
+      ^
 SyntaxError: Identifier 'x' has already been declared
diff --git a/test/mjsunit/apply.js b/test/mjsunit/apply.js
index fdd032d..7ce6acc 100644
--- a/test/mjsunit/apply.js
+++ b/test/mjsunit/apply.js
@@ -114,7 +114,7 @@
   return arguments.length + arguments[arguments.length - 1];
 }
 
-for (var j = 1; j < 0x4000000; j <<= 1) {
+for (var j = 1; j < 0x400000; j <<= 1) {
   try {
     var a = %NormalizeElements([]);
     a.length = j;
@@ -122,7 +122,7 @@
     assertEquals(42 + j, al.apply(345, a));
   } catch (e) {
     assertTrue(e.toString().indexOf("Maximum call stack size exceeded") != -1);
-    for (; j < 0x4000000; j <<= 1) {
+    for (; j < 0x400000; j <<= 1) {
       var caught = false;
       try {
         a = %NormalizeElements([]);
diff --git a/test/mjsunit/arguments-opt.js b/test/mjsunit/arguments-opt.js
deleted file mode 100644
index b8280b4..0000000
--- a/test/mjsunit/arguments-opt.js
+++ /dev/null
@@ -1,132 +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: --allow-natives-syntax
-
-function L0() {
-  return %_ArgumentsLength();
-}
-
-function L1(a) {
-  return %_ArgumentsLength();
-}
-
-function L5(a,b,c,d,e) {
-  return %_ArgumentsLength();
-}
-
-
-assertEquals(0, L0());
-assertEquals(1, L0(1));
-assertEquals(2, L0(1,2));
-assertEquals(5, L0(1,2,3,4,5));
-
-assertEquals(0, L1());
-assertEquals(1, L1(1));
-assertEquals(2, L1(1,2));
-assertEquals(5, L1(1,2,3,4,5));
-
-assertEquals(0, L5());
-assertEquals(1, L5(1));
-assertEquals(2, L5(1,2));
-assertEquals(5, L5(1,2,3,4,5));
-
-
-function A(key) {
-  return %_Arguments(key);
-}
-
-// Integer access.
-assertEquals(0, A(0));
-assertEquals(0, A(0,1));
-assertEquals(2, A(1,2));
-assertEquals(2, A(1,2,3,4,5));
-assertEquals(5, A(4,2,3,4,5));
-assertTrue(typeof A(1) == 'undefined');
-assertTrue(typeof A(3,2,1) == 'undefined');
-
-// Out-of-bounds integer access with and without argument
-// adaptor frames.
-assertTrue(typeof(A(-10000)) == 'undefined');
-assertTrue(typeof(A(-10000, 0)) == 'undefined');
-assertTrue(typeof(A(-1)) == 'undefined');
-assertTrue(typeof(A(-1, 0)) == 'undefined');
-assertTrue(typeof(A(10000)) == 'undefined');
-assertTrue(typeof(A(10000, 0)) == 'undefined');
-
-// String access.
-assertEquals('0', A('0'));
-assertEquals('0', A('0',1));
-assertEquals(2, A('1',2));
-assertEquals(2, A('1',2,3,4,5));
-assertEquals(5, A('4',2,3,4,5));
-assertEquals('undefined', typeof A('1'));
-assertEquals('undefined', typeof A('3',2,1));
-assertEquals(A, A('callee'));
-assertEquals(1, A('length'));
-assertEquals(2, A('length',2));
-assertEquals(5, A('length',2,3,4,5));
-assertEquals({}.toString, A('toString'));
-assertEquals({}.isPrototypeOf, A('isPrototypeOf'));
-assertEquals('undefined', typeof A('xxx'));
-
-// Object access.
-function O(key) {
-  return { toString: function() { return key; } };
-}
-
-var O0 = O(0);
-assertSame(O0, A(O0));
-assertSame(O0, A(O0,1));
-assertEquals(2, A(O(1),2));
-assertEquals(2, A(O(1),2,3,4,5));
-assertEquals(5, A(O(4),2,3,4,5));
-assertTrue(typeof A(O(1)) == 'undefined');
-assertTrue(typeof A(O(3),2,1) == 'undefined');
-
-O0 = O('0');
-assertSame(O0, A(O0));
-assertSame(O0, A(O0,1));
-assertEquals(2, A(O('1'),2));
-assertEquals(2, A(O('1'),2,3,4,5));
-assertEquals(5, A(O('4'),2,3,4,5));
-assertTrue(typeof A(O('1')) == 'undefined');
-assertTrue(typeof A(O('3'),2,1) == 'undefined');
-assertEquals(A, A(O('callee')));
-assertEquals(1, A(O('length')));
-assertEquals(2, A(O('length'),2));
-assertEquals(5, A(O('length'),2,3,4,5));
-assertEquals({}.toString, A(O('toString')));
-assertEquals({}.isPrototypeOf, A(O('isPrototypeOf')));
-assertTrue(typeof A(O('xxx')) == 'undefined');
-
-// Make sure that out-of-bounds access do lookups in the
-// prototype chain.
-Object.prototype[5] = 42;
-assertEquals(42, A(5));
-Object.prototype[-5] = 87;
-assertEquals(87, A(-5));
diff --git a/test/mjsunit/array-concat.js b/test/mjsunit/array-concat.js
index 97bd85a..6e25b5c 100644
--- a/test/mjsunit/array-concat.js
+++ b/test/mjsunit/array-concat.js
@@ -29,6 +29,19 @@
  * @fileoverview Test concat on small and large arrays
  */
 
+
+(function testStringWrapperConcat() {
+  var concat = Array.prototype.concat;
+  var str = new String('abcd');
+  assertEquals([1,2,3,new String('abcd')], [1, 2, 3].concat(str));
+  assertEquals([new String("abcd")], concat.call(str));
+
+  var array = [1, 2, 3];
+  array.__proto__ = str;
+  array.length = 4;
+  assertEquals([1,2,3,'d'], concat.call(array));
+})()
+
 var poses;
 
 poses = [140, 4000000000];
diff --git a/test/mjsunit/array-sort.js b/test/mjsunit/array-sort.js
index 36608f5..ae9f6ef 100644
--- a/test/mjsunit/array-sort.js
+++ b/test/mjsunit/array-sort.js
@@ -464,3 +464,18 @@
   assertEquals(0, Number(Array.prototype.sort.call(0)));
 }
 TestSortToObject();
+
+function TestSortOnProxy() {
+  {
+    var p = new Proxy([2,1,3], {});
+    assertEquals([1,2,3], p.sort());
+  }
+
+  {
+    function f() { return arguments };
+    var a = f(2,1,3);
+    a.__proto__ = new Proxy({}, {});
+    assertEquals([1,2,3], [...(Array.prototype.sort.apply(a))]);
+  }
+}
+TestSortOnProxy();
diff --git a/test/mjsunit/compiler/debug-catch-prediction.js b/test/mjsunit/compiler/debug-catch-prediction.js
new file mode 100644
index 0000000..34d3afd
--- /dev/null
+++ b/test/mjsunit/compiler/debug-catch-prediction.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: --expose-debug-as debug --allow-natives-syntax
+
+// Test debug event catch prediction for thrown exceptions. We distinguish
+// between "caught" and "uncaught" based on the following assumptions:
+//  1) try-catch   : Will always catch the exception.
+//  2) try-finally : Will always re-throw the exception.
+
+Debug = debug.Debug;
+
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      log.push([event_data.exception(), event_data.uncaught()]);
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+(function TryCatch() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      throw "boom" + a;
+    } catch(e) {
+      return e;
+    }
+  }
+  assertEquals("boom1", f(1));
+  assertEquals("boom2", f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("boom3", f(3));
+  print("Collect log:", log);
+  assertEquals([["boom1",false], ["boom2",false], ["boom3",false]], log);
+})();
+
+(function TryFinally() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      throw "baem" + a;
+    } finally {
+      return a + 10;
+    }
+  }
+  assertEquals(11, f(1));
+  assertEquals(12, f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(13, f(3));
+  print("Collect log:", log);
+  assertEquals([["baem1",true], ["baem2",true], ["baem3",true]], log);
+})();
+
+(function TryCatchFinally() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      throw "wosh" + a;
+    } catch(e) {
+      return e + a;
+    } finally {
+      // Nothing.
+    }
+  }
+  assertEquals("wosh11", f(1));
+  assertEquals("wosh22", f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("wosh33", f(3));
+  print("Collect log:", log);
+  assertEquals([["wosh1",false], ["wosh2",false], ["wosh3",false]], log);
+})();
+
+(function TryCatchNestedFinally() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      try {
+        throw "bang" + a;
+      } finally {
+        // Nothing.
+      }
+    } catch(e) {
+      return e + a;
+    }
+  }
+  assertEquals("bang11", f(1));
+  assertEquals("bang22", f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("bang33", f(3));
+  print("Collect log:", log);
+  assertEquals([["bang1",false], ["bang2",false], ["bang3",false]], log);
+})();
+
+(function TryFinallyNestedCatch() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      try {
+        throw "peng" + a;
+      } catch(e) {
+        return e
+      }
+    } finally {
+      return a + 10;
+    }
+  }
+  assertEquals(11, f(1));
+  assertEquals(12, f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(13, f(3));
+  print("Collect log:", log);
+  assertEquals([["peng1",false], ["peng2",false], ["peng3",false]], log);
+})();
+
+(function TryFinallyNestedFinally() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      try {
+        throw "oops" + a;
+      } finally {
+        // Nothing.
+      }
+    } finally {
+      return a + 10;
+    }
+  }
+  assertEquals(11, f(1));
+  assertEquals(12, f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(13, f(3));
+  print("Collect log:", log);
+  assertEquals([["oops1",true], ["oops2",true], ["oops3",true]], log);
+})();
diff --git a/test/mjsunit/regress/setvalueof-deopt.js b/test/mjsunit/compiler/deopt-materialize-accumulator.js
similarity index 78%
rename from test/mjsunit/regress/setvalueof-deopt.js
rename to test/mjsunit/compiler/deopt-materialize-accumulator.js
index 8c42c8a..c80e329 100644
--- a/test/mjsunit/regress/setvalueof-deopt.js
+++ b/test/mjsunit/compiler/deopt-materialize-accumulator.js
@@ -1,4 +1,4 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
+// Copyright 2016 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:
@@ -26,17 +26,16 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax
+//
+// Tests that Turbofan correctly materializes values which are in the
+// interpreters accumulator during deopt.
 
-function g(x, y) {
-  return y;
+var global = 3;
+function f(a) {
+  // This will trigger a deopt since global was previously a SMI, with the
+  // accumulator holding an unboxed double which needs materialized.
+  global = %_MathSqrt(a);
 }
-
-function f(deopt) {
-  return g(%_SetValueOf(1, 1), deopt + 0);
-}
-
-f(0);
-f(0);
-f(0);
 %OptimizeFunctionOnNextCall(f);
-assertEquals("result0", f("result"));
+f(0.25);
+assertEquals(0.5, global);
diff --git a/test/mjsunit/compiler/double-array-to-global.js b/test/mjsunit/compiler/double-array-to-global.js
new file mode 100644
index 0000000..e221d90
--- /dev/null
+++ b/test/mjsunit/compiler/double-array-to-global.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.
+
+// Flags: --allow-natives-syntax
+
+var a = [-0, 0];
+var b;
+function foo(a) {
+  for (var i = 0; i < 2; ++i) {
+    b = a[i];
+  }
+}
+foo(a);
+foo(a);
+%OptimizeFunctionOnNextCall(foo);
+foo(a);
diff --git a/test/mjsunit/compiler/inline-arguments.js b/test/mjsunit/compiler/inline-arguments.js
index d52f31b..1337ab2 100644
--- a/test/mjsunit/compiler/inline-arguments.js
+++ b/test/mjsunit/compiler/inline-arguments.js
@@ -309,29 +309,3 @@
   delete forceDeopt.deopt;
   outer();
 })();
-
-
-// Test inlining of functions with %_Arguments and %_ArgumentsLength intrinsic.
-(function () {
-  function inner(len,a,b,c) {
-    assertSame(len, %_ArgumentsLength());
-    for (var i = 1; i < len; ++i) {
-      var c = String.fromCharCode(96 + i);
-      assertSame(c, %_Arguments(i));
-    }
-  }
-
-  function outer() {
-    inner(1);
-    inner(2, 'a');
-    inner(3, 'a', 'b');
-    inner(4, 'a', 'b', 'c');
-    inner(5, 'a', 'b', 'c', 'd');
-    inner(6, 'a', 'b', 'c', 'd', 'e');
-  }
-
-  outer();
-  outer();
-  %OptimizeFunctionOnNextCall(outer);
-  outer();
-})();
diff --git a/test/mjsunit/compiler/minus-zero.js b/test/mjsunit/compiler/minus-zero.js
index c161257..ac66350 100644
--- a/test/mjsunit/compiler/minus-zero.js
+++ b/test/mjsunit/compiler/minus-zero.js
@@ -37,31 +37,8 @@
 assertEquals(-0, add(-0, -0));
 
 
-function test(x, y) {
-  assertTrue(%_IsMinusZero(-0));
-  assertTrue(%_IsMinusZero(1/(-Infinity)));
-  assertTrue(%_IsMinusZero(x));
-
-  assertFalse(%_IsMinusZero(0));
-  assertFalse(%_IsMinusZero(1/Infinity));
-  assertFalse(%_IsMinusZero(0.1));
-  assertFalse(%_IsMinusZero(-0.2));
-  assertFalse(%_IsMinusZero({}));
-  assertFalse(%_IsMinusZero(""));
-  assertFalse(%_IsMinusZero("-0"));
-  assertFalse(%_IsMinusZero(function() {}));
-  assertFalse(%_IsMinusZero(y));
-}
-
-test(-0, 1.2);
-test(-0, 1.2);
-%OptimizeFunctionOnNextCall(test);
-test(-0, 1.2);
-assertOptimized(test);
-
-
 function testsin() {
-  assertTrue(%_IsMinusZero(Math.sin(-0)));
+  assertEquals(-0, Math.sin(-0));
 }
 
 testsin();
@@ -71,8 +48,7 @@
 
 
 function testfloor() {
-  assertTrue(%_IsMinusZero(Math.floor(-0)));
-  assertFalse(%_IsMinusZero(Math.floor(2)));
+  assertEquals(-0, Math.floor(-0));
 }
 
 testfloor();
diff --git a/test/mjsunit/compiler/optimized-for-in.js b/test/mjsunit/compiler/optimized-for-in.js
index f3ff6be..d93344e 100644
--- a/test/mjsunit/compiler/optimized-for-in.js
+++ b/test/mjsunit/compiler/optimized-for-in.js
@@ -25,8 +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: --optimize-for-in --allow-natives-syntax
-// Flags: --no-concurrent-osr
+// Flags: --allow-natives-syntax --no-concurrent-osr
 
 // Test for-in support in Crankshaft.  For simplicity this tests assumes certain
 // fixed iteration order for properties and will have to be adjusted if V8
diff --git a/test/mjsunit/compiler/regress-1085.js b/test/mjsunit/compiler/regress-1085.js
index cea587f..533cf59 100644
--- a/test/mjsunit/compiler/regress-1085.js
+++ b/test/mjsunit/compiler/regress-1085.js
@@ -33,6 +33,5 @@
 
 for (var i = 0; i < 5; ++i) f(1);
 %OptimizeFunctionOnNextCall(f);
-%OptimizeFunctionOnNextCall(Math.min);
 
 assertEquals(-Infinity, f(-0));
diff --git a/test/mjsunit/compiler/regress-dead-throw-inlining.js b/test/mjsunit/compiler/regress-dead-throw-inlining.js
new file mode 100644
index 0000000..097a20b
--- /dev/null
+++ b/test/mjsunit/compiler/regress-dead-throw-inlining.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
+
+function g() { if (false) throw 0; }
+function f() { g(); }
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
diff --git a/test/mjsunit/compiler/regress-max.js b/test/mjsunit/compiler/regress-max.js
index ee2fd58..7556f2f 100644
--- a/test/mjsunit/compiler/regress-max.js
+++ b/test/mjsunit/compiler/regress-max.js
@@ -29,7 +29,6 @@
 
 // Test Math.max with negative zero as input.
 for (var i = 0; i < 5; i++) Math.max(0, 0);
-%OptimizeFunctionOnNextCall(Math.max);
 Math.max(0, 0);
 
 var r = Math.max(-0, -0);
diff --git a/test/mjsunit/compiler/try-catch-deopt.js b/test/mjsunit/compiler/try-catch-deopt.js
new file mode 100644
index 0000000..2b6372c
--- /dev/null
+++ b/test/mjsunit/compiler/try-catch-deopt.js
@@ -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.
+
+// Flags: --allow-natives-syntax
+
+(function LazyDeoptFromTryBlock() {
+  function g(dummy) {
+    %DeoptimizeFunction(f);
+    throw 42;
+  }
+
+  function f() {
+    var a = 1;
+    try {
+      var dummy = 2;  // perturb the stack height.
+      g(dummy);
+    } catch (e) {
+      return e + a;
+    }
+  }
+
+  assertEquals(43, f());
+  assertEquals(43, f());
+  %NeverOptimizeFunction(g);
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(43, f());
+})();
+
+
+(function LazyDeoptDoublyNestedTryBlock() {
+  function g(dummy) {
+    %DeoptimizeFunction(f);
+    throw 42;
+  }
+
+  function f() {
+    var b;
+    try {
+      var a = 1;
+      try {
+        var dummy = 2;  // perturb the stack height.
+        g(dummy);
+      } catch (e) {
+        b = e + a;
+      }
+    } catch (e) {
+      return 0;
+    }
+    return b;
+  }
+
+  assertEquals(43, f());
+  assertEquals(43, f());
+  %NeverOptimizeFunction(g);
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(43, f());
+})();
+
+(function LazyDeoptInlinedTry() {
+  function g(dummy) {
+    %DeoptimizeFunction(f);
+    %DeoptimizeFunction(h);
+    throw 42;
+  }
+
+  function h() {
+    var a = 1;
+    try {
+      var dummy = 2;  // perturb the stack height.
+      g(dummy);
+    } catch (e) {
+      b = e + a;
+    }
+    return b;
+  }
+
+  function f() {
+    var c = 1;
+    return h() + 1;
+  }
+
+  assertEquals(44, f());
+  assertEquals(44, f());
+  %NeverOptimizeFunction(g);
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(44, f());
+})();
+
+(function LazyDeoptInlinedIntoTry() {
+  function g(c) {
+    %DeoptimizeFunction(f);
+    %DeoptimizeFunction(h);
+    throw c;
+  }
+
+  function h(c) {
+    return g(c);
+  }
+
+  function f() {
+    var a = 1;
+    try {
+      var c = 42;  // perturb the stack height.
+      h(c);
+    } catch (e) {
+      a += e;
+    }
+    return a;
+  }
+
+  assertEquals(43, f());
+  assertEquals(43, f());
+  %NeverOptimizeFunction(g);
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(43, f());
+})();
+
+(function LazyDeoptTryBlockContextCatch() {
+  var global = 0;
+
+  function g() {
+    %DeoptimizeFunction(f);
+    throw "boom!";
+  }
+
+  function f(a) {
+    var x = a + 23
+    try {
+      let y = a + 42;
+      function capture() { return x + y }
+      g();
+    } catch(e) {
+      global = x;
+    }
+    return x;
+  }
+  assertEquals(23, f(0));
+  assertEquals(24, f(1));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(25, f(2));
+  assertEquals(25, global);
+})();
+
+(function LazyDeoptTryBlockFinally() {
+  var global = 0;
+
+  function g() {
+    %DeoptimizeFunction(f);
+    throw "boom!";
+  }
+
+  function f(a) {
+    var x = a + 23
+    try {
+      let y = a + 42;
+      function capture() { return x + y }
+      g();
+    } finally {
+      global = x;
+    }
+    return x;
+  }
+  assertThrows(function() { f(0) });
+  assertThrows(function() { f(1) });
+  %OptimizeFunctionOnNextCall(f);
+  assertThrowsEquals(function() { f(2) }, "boom!");
+  assertEquals(25, global);
+})();
+
+(function LazyDeoptTryCatchContextCatch() {
+  var global = 0;
+
+  function g() {
+    %DeoptimizeFunction(f);
+    throw 5;
+  }
+
+  function f(a) {
+    var x = a + 23
+    try {
+      try {
+        throw 1;
+      } catch(e2) {
+        function capture() { return x + y }
+        g();
+      }
+    } catch(e) {
+      global = x + e;
+    }
+    return x;
+  }
+  assertEquals(23, f(0));
+  assertEquals(24, f(1));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(25, f(2));
+  assertEquals(30, global);
+})();
+
+(function LazyDeoptTryWithContextCatch() {
+  var global = 0;
+
+  function g() {
+    %DeoptimizeFunction(f);
+    throw 5;
+  }
+
+  function f(a) {
+    var x = a + 23
+    try {
+      with ({ y : a + 42 }) {
+        function capture() { return x + y }
+        g();
+      }
+    } catch(e) {
+      global = x + e;
+    }
+    return x;
+  }
+  assertEquals(23, f(0));
+  assertEquals(24, f(1));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(25, f(2));
+  assertEquals(30, global);
+})();
diff --git a/test/mjsunit/compiler/try-context.js b/test/mjsunit/compiler/try-context.js
new file mode 100644
index 0000000..4e6d9b0
--- /dev/null
+++ b/test/mjsunit/compiler/try-context.js
@@ -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.
+
+// Flags: --allow-natives-syntax
+
+(function TryBlockCatch() {
+  var global = 0;
+  function f(a) {
+    var x = a + 23
+    try {
+      let y = a + 42;
+      function capture() { return x + y }
+      throw "boom!";
+    } catch(e) {
+      global = x;
+    }
+    return x;
+  }
+  assertEquals(23, f(0));
+  assertEquals(24, f(1));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(25, f(2));
+  assertEquals(25, global);
+})();
+
+(function TryBlockFinally() {
+  var global = 0;
+  function f(a) {
+    var x = a + 23
+    try {
+      let y = a + 42;
+      function capture() { return x + y }
+      throw "boom!";
+    } finally {
+      global = x;
+    }
+    return x;
+  }
+  assertThrows(function() { f(0) });
+  assertThrows(function() { f(1) });
+  %OptimizeFunctionOnNextCall(f);
+  assertThrows(function() { f(2) });
+  assertEquals(25, global);
+})();
+
+(function TryCatchCatch() {
+  var global = 0;
+  function f(a) {
+    var x = a + 23
+    try {
+      try {
+        throw "boom!";
+      } catch(e2) {
+        function capture() { return x + y }
+        throw "boom!";
+      }
+    } catch(e) {
+      global = x;
+    }
+    return x;
+  }
+  assertEquals(23, f(0));
+  assertEquals(24, f(1));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(25, f(2));
+  assertEquals(25, global);
+})();
+
+(function TryWithCatch() {
+  var global = 0;
+  function f(a) {
+    var x = a + 23
+    try {
+      with ({ y : a + 42 }) {
+        function capture() { return x + y }
+        throw "boom!";
+      }
+    } catch(e) {
+      global = x;
+    }
+    return x;
+  }
+  assertEquals(23, f(0));
+  assertEquals(24, f(1));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(25, f(2));
+  assertEquals(25, global);
+})();
diff --git a/test/mjsunit/compiler/try-finally-deopt.js b/test/mjsunit/compiler/try-finally-deopt.js
new file mode 100644
index 0000000..455bf34
--- /dev/null
+++ b/test/mjsunit/compiler/try-finally-deopt.js
@@ -0,0 +1,249 @@
+// Copyright 2016 the V8 project 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 DeoptimizeFinallyFallThrough() {
+  var global = 0;
+  function f() {
+    var a = 1;
+    try {
+      global = 1;
+    } finally {
+      global = 42;
+      %DeoptimizeNow();
+    }
+    return global + a;
+  }
+
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(43, f());
+  assertEquals(42, global);
+})();
+
+(function DeoptimizeFinallyReturn() {
+  var global = 0;
+  function f() {
+    try {
+      return 10;
+    } finally {
+      global = 42;
+      %DeoptimizeNow();
+    }
+    return 1;
+  }
+
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(10, f());
+  assertEquals(42, global);
+})();
+
+(function DeoptimizeFinallyReturnDoublyNested() {
+  var global = 0;
+  function f() {
+    try {
+      try {
+        return 10;
+      } finally {
+        global += 21;
+        %DeoptimizeNow();
+      }
+    } finally {
+      global += 21;
+    }
+    return 1;
+  }
+
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  global = 0;
+  assertEquals(10, f());
+  assertEquals(42, global);
+})();
+
+(function DeoptimizeOuterFinallyReturnDoublyNested() {
+  var global = 0;
+  function f() {
+    try {
+      try {
+        return 10;
+      } finally {
+        global += 21;
+      }
+    } finally {
+      global += 21;
+      %DeoptimizeNow();
+    }
+    return 1;
+  }
+
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  global = 0;
+  assertEquals(10, f());
+  assertEquals(42, global);
+})();
+
+(function DeoptimizeFinallyThrow() {
+  var global = 0;
+  function f() {
+    try {
+      global = 21;
+      throw 1;
+      global = 2;
+    } finally {
+      global += 21;
+      %DeoptimizeNow();
+    }
+    global = 3;
+    return 1;
+  }
+
+  try { f(); } catch(e) {}
+  try { f(); } catch(e) {}
+  %OptimizeFunctionOnNextCall(f);
+  assertThrowsEquals(f, 1);
+  assertEquals(42, global);
+})();
+
+(function DeoptimizeFinallyThrowNested() {
+  var global = 0;
+  function f() {
+    try {
+      try {
+        global = 10;
+        throw 1;
+        global = 2;
+      } finally {
+        global += 11;
+        %DeoptimizeNow();
+      }
+      global = 4;
+    } finally {
+      global += 21;
+    }
+    global = 3;
+    return 1;
+  }
+
+  try { f(); } catch(e) {}
+  try { f(); } catch(e) {}
+  %OptimizeFunctionOnNextCall(f);
+  assertThrowsEquals(f, 1);
+  assertEquals(42, global);
+})();
+
+(function DeoptimizeFinallyContinue() {
+  var global = 0;
+  function f() {
+    global = 0;
+    for (var i = 0; i < 2; i++) {
+      try {
+        if (i == 0) continue;
+        global += 10;
+      } finally {
+        global += 6;
+        %DeoptimizeNow();
+      }
+      global += 20;
+    }
+    return 1;
+  }
+
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(1, f());
+  assertEquals(42, global);
+})();
+
+(function DeoptimizeFinallyContinueNestedTry() {
+  var global = 0;
+  function f() {
+    global = 0;
+    for (var i = 0; i < 2; i++) {
+      try {
+        try {
+          if (i == 0) continue;
+          global += 5;
+        } finally {
+          global += 4;
+          %DeoptimizeNow();
+        }
+        global += 5;
+      } finally {
+        global += 2;
+      }
+      global += 20;
+    }
+    return 1;
+  }
+
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(1, f());
+  assertEquals(42, global);
+})();
+
+(function DeoptimizeFinallyBreak() {
+  var global = 0;
+  function f() {
+    global = 0;
+    for (var i = 0; i < 2; i++) {
+      try {
+        global += 20;
+        if (i == 0) break;
+        global += 5;
+      } finally {
+        global += 22;
+        %DeoptimizeNow();
+      }
+      global += 5;
+    }
+    return 1;
+  }
+
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(1, f());
+  assertEquals(42, global);
+})();
+
+(function DeoptimizeFinallyBreakNested() {
+  var global = 0;
+  function f() {
+    global = 0;
+    for (var i = 0; i < 2; i++) {
+      try {
+        try {
+          global += 20;
+          if (i == 0) break;
+          global += 5;
+        } finally {
+          global += 12;
+          %DeoptimizeNow();
+        }
+        global += 8;
+      } finally {
+        global += 10;
+      }
+      global += 5;
+    }
+    return 1;
+  }
+
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(1, f());
+  assertEquals(42, global);
+})();
diff --git a/test/mjsunit/constant-fold-control-instructions.js b/test/mjsunit/constant-fold-control-instructions.js
index eb49945..20900d6 100644
--- a/test/mjsunit/constant-fold-control-instructions.js
+++ b/test/mjsunit/constant-fold-control-instructions.js
@@ -24,15 +24,8 @@
   assertTrue(%_IsArray([1]));
   assertFalse(%_IsArray(function() {}));
 
-  assertTrue(%_IsFunction(function() {}));
-  assertFalse(%_IsFunction(null));
-
   assertTrue(%_IsJSReceiver(new Date()));
   assertFalse(%_IsJSReceiver(1));
-
-  assertTrue(%_IsMinusZero(-0.0));
-  assertFalse(%_IsMinusZero(1));
-  assertFalse(%_IsMinusZero(""));
 }
 
 
diff --git a/test/mjsunit/debug-changebreakpoint.js b/test/mjsunit/debug-changebreakpoint.js
index 897c3e3..ad43b17 100644
--- a/test/mjsunit/debug-changebreakpoint.js
+++ b/test/mjsunit/debug-changebreakpoint.js
@@ -79,12 +79,6 @@
     testArguments(dcp, '{' + bp_str + ',"enabled":"false"}', true);
     testArguments(dcp, '{' + bp_str + ',"condition":"1==2"}', true);
     testArguments(dcp, '{' + bp_str + ',"condition":"false"}', true);
-    testArguments(dcp, '{' + bp_str + ',"ignoreCount":7}', true);
-    testArguments(dcp, '{' + bp_str + ',"ignoreCount":0}', true);
-    testArguments(
-        dcp,
-        '{' + bp_str + ',"enabled":"true","condition":"false","ignoreCount":0}',
-        true);
 
     // Indicate that all was processed.
     listenerComplete = true;
diff --git a/test/mjsunit/debug-conditional-breakpoints.js b/test/mjsunit/debug-conditional-breakpoints.js
index 6248437..4414897 100644
--- a/test/mjsunit/debug-conditional-breakpoints.js
+++ b/test/mjsunit/debug-conditional-breakpoints.js
@@ -53,7 +53,6 @@
 bp = Debug.setBreakPoint(f, 0, 0, '{{{');
 f();
 assertEquals(0, break_point_hit_count);
-assertEquals(0, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 
 // Conditional breakpoint which evaluates to false.
@@ -61,7 +60,6 @@
 bp = Debug.setBreakPoint(f, 0, 0, 'false');
 f();
 assertEquals(0, break_point_hit_count);
-assertEquals(0, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 
 // Conditional breakpoint which evaluates to true.
@@ -69,7 +67,6 @@
 bp = Debug.setBreakPoint(f, 0, 0, 'true');
 f();
 assertEquals(1, break_point_hit_count);
-assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 
 // Conditional breakpoint which different types of quotes.
@@ -77,13 +74,11 @@
 bp = Debug.setBreakPoint(f, 0, 0, '"a" == "a"');
 f();
 assertEquals(1, break_point_hit_count);
-assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 break_point_hit_count = 0;
 bp = Debug.setBreakPoint(f, 0, 0, "'a' == 'a'");
 f();
 assertEquals(1, break_point_hit_count);
-assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 
 // Changing condition.
@@ -91,15 +86,12 @@
 bp = Debug.setBreakPoint(f, 0, 0, '"ab".indexOf("b") > 0');
 f();
 assertEquals(1, break_point_hit_count);
-assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
 Debug.changeBreakPointCondition(bp, 'Math.sin(Math.PI/2) > 1');
 f();
 assertEquals(1, break_point_hit_count);
-assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
 Debug.changeBreakPointCondition(bp, '1==1');
 f();
 assertEquals(2, break_point_hit_count);
-assertEquals(2, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 
 // Conditional breakpoint which checks global variable.
@@ -107,11 +99,9 @@
 bp = Debug.setBreakPoint(f, 0, 0, 'x==1');
 f();
 assertEquals(0, break_point_hit_count);
-assertEquals(0, Debug.findBreakPoint(bp, false).hit_count());
 x=1;
 f();
 assertEquals(1, break_point_hit_count);
-assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 
 // Conditional breakpoint which checks global variable.
@@ -121,7 +111,6 @@
   g();
 }
 assertEquals(5, break_point_hit_count);
-assertEquals(5, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 
 // Conditional breakpoint which checks a parameter.
@@ -131,7 +120,6 @@
   g();
 }
 assertEquals(5, break_point_hit_count);
-assertEquals(5, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 
 // Conditional breakpoint which checks a local variable.
@@ -141,7 +129,6 @@
   g();
 }
 assertEquals(5, break_point_hit_count);
-assertEquals(5, Debug.findBreakPoint(bp, false).hit_count());
 Debug.clearBreakPoint(bp);
 
 // Multiple conditional breakpoint which the same condition.
@@ -152,8 +139,6 @@
   g();
 }
 assertEquals(5, break_point_hit_count);
-assertEquals(5, Debug.findBreakPoint(bp1, false).hit_count());
-assertEquals(5, Debug.findBreakPoint(bp2, false).hit_count());
 Debug.clearBreakPoint(bp1);
 Debug.clearBreakPoint(bp2);
 
@@ -165,7 +150,5 @@
   g();
 }
 assertEquals(10, break_point_hit_count);
-assertEquals(5, Debug.findBreakPoint(bp1, false).hit_count());
-assertEquals(5, Debug.findBreakPoint(bp2, false).hit_count());
 Debug.clearBreakPoint(bp1);
 Debug.clearBreakPoint(bp2);
diff --git a/test/mjsunit/debug-ignore-breakpoints.js b/test/mjsunit/debug-ignore-breakpoints.js
deleted file mode 100644
index 3cb283b..0000000
--- a/test/mjsunit/debug-ignore-breakpoints.js
+++ /dev/null
@@ -1,88 +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
-// Get the Debug object exposed from the debug context global object.
-Debug = debug.Debug
-
-// Simple debug event handler which just counts the number of break points hit.
-var break_point_hit_count;
-
-function listener(event, exec_state, event_data, data) {
-  if (event == Debug.DebugEvent.Break) {
-    break_point_hit_count++;
-  }
-};
-
-// Add the debug event listener.
-Debug.setListener(listener);
-
-// Test function.
-function f() {};
-
-// This tests ignore of break points including the case with several
-// break points in the same location.
-break_point_hit_count = 0;
-
-// Set a breakpoint in f.
-bp1 = Debug.setBreakPoint(f);
-
-// Try ignore count of 1.
-Debug.changeBreakPointIgnoreCount(bp1, 1);
-f();
-assertEquals(0, break_point_hit_count);
-f();
-assertEquals(1, break_point_hit_count);
-
-// Set another breakpoint in f at the same place.
-bp2 = Debug.setBreakPoint(f);
-f();
-assertEquals(2, break_point_hit_count);
-
-// Set different ignore counts.
-Debug.changeBreakPointIgnoreCount(bp1, 2);
-Debug.changeBreakPointIgnoreCount(bp2, 4);
-f();
-assertEquals(2, break_point_hit_count);
-f();
-assertEquals(2, break_point_hit_count);
-f();
-assertEquals(3, break_point_hit_count);
-f();
-assertEquals(4, break_point_hit_count);
-
-// Set different ignore counts (opposite).
-Debug.changeBreakPointIgnoreCount(bp1, 4);
-Debug.changeBreakPointIgnoreCount(bp2, 2);
-f();
-assertEquals(4, break_point_hit_count);
-f();
-assertEquals(4, break_point_hit_count);
-f();
-assertEquals(5, break_point_hit_count);
-f();
-assertEquals(6, break_point_hit_count);
diff --git a/test/mjsunit/debug-negative-break-points.js b/test/mjsunit/debug-negative-break-points.js
new file mode 100644
index 0000000..1eb8943
--- /dev/null
+++ b/test/mjsunit/debug-negative-break-points.js
@@ -0,0 +1,99 @@
+// Copyright 2016 the V8 project 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 break_count = 0;
+var exception_count = 0;
+
+function assertCount(expected_breaks, expected_exceptions) {
+  assertEquals(expected_breaks, break_count);
+  assertEquals(expected_exceptions, exception_count);
+}
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_count++;
+  } else if (event == Debug.DebugEvent.Exception) {
+    exception_count++;
+  }
+}
+
+function f(x) {
+  debugger;
+  return x + 1;
+}
+
+function g(x) {
+  try {
+    throw x;
+  } catch (e) {
+  }
+}
+
+function h(x) {
+  var a = undefined;
+  try {
+    var x = a();
+  } catch (e) {
+  }
+}
+
+Debug.setListener(listener);
+
+assertCount(0, 0);
+f(0);
+assertCount(1, 0);
+g(0);
+assertCount(1, 0);
+
+Debug.setBreakOnException();
+f(0);
+assertCount(2, 0);
+g(0);
+assertCount(2, 1);
+
+Debug.setBreakPoint(f, 1, 0, "x == 1");
+f(1);
+assertCount(3, 1);
+f(2);
+assertCount(3, 1);
+f(1);
+assertCount(4, 1);
+
+Debug.setBreakPoint(f, 1, 0, "x > 0");
+f(1);
+assertCount(5, 1);
+f(0);
+assertCount(5, 1);
+
+Debug.setBreakPoint(g, 2, 0, "1 == 2");
+g(1);
+assertCount(5, 1);
+
+Debug.setBreakPoint(g, 2, 0, "x == 1");
+g(1);
+assertCount(6, 2);
+g(2);
+assertCount(6, 2);
+g(1);
+assertCount(7, 3);
+
+Debug.setBreakPoint(g, 2, 0, "x > 0");
+g(1);
+assertCount(8, 4);
+g(0);
+assertCount(8, 4);
+
+h(0);
+assertCount(8, 5);
+Debug.setBreakPoint(h, 3, 0, "x > 0");
+h(1);
+assertCount(9, 6);
+h(0);
+assertCount(9, 6);
+
+Debug.clearBreakOnException();
+Debug.setListener(null);
diff --git a/test/mjsunit/debug-script.js b/test/mjsunit/debug-script.js
index 8874960..5396415 100644
--- a/test/mjsunit/debug-script.js
+++ b/test/mjsunit/debug-script.js
@@ -73,8 +73,8 @@
 
 // This has to be updated if the number of native scripts change.
 assertEquals(%NativeScriptsCount(), named_native_count);
-// Only the 'gc' extension is loaded.
-assertEquals(1, extension_count);
+// The 'gc' extension and one or two extras scripts are loaded.
+assertTrue(extension_count == 2 || extension_count == 3);
 // This script and mjsunit.js has been loaded.  If using d8, d8 loads
 // a normal script during startup too.
 assertTrue(normal_count == 2 || normal_count == 3);
diff --git a/test/mjsunit/debug-setbreakpoint.js b/test/mjsunit/debug-setbreakpoint.js
index bc23021..7c996e5 100644
--- a/test/mjsunit/debug-setbreakpoint.js
+++ b/test/mjsunit/debug-setbreakpoint.js
@@ -88,7 +88,6 @@
     testArguments(dcp, '{"type":"function","target":1}', false);
     testArguments(dcp, '{"type":"function","target":"f","line":-1}', false);
     testArguments(dcp, '{"type":"function","target":"f","column":-1}', false);
-    testArguments(dcp, '{"type":"function","target":"f","ignoreCount":-1}', false);
     testArguments(dcp, '{"type":"handle","target":"-1"}', false);
     mirror = debug.MakeMirror(o);
     testArguments(dcp, '{"type":"handle","target":' + mirror.handle() + '}', false);
@@ -101,7 +100,6 @@
     testArguments(dcp, '{"type":"function","target":"f","condition":"i == 1"}', true, false);
     testArguments(dcp, '{"type":"function","target":"f","enabled":true}', true, false);
     testArguments(dcp, '{"type":"function","target":"f","enabled":false}', true, false);
-    testArguments(dcp, '{"type":"function","target":"f","ignoreCount":7}', true, false);
 
     testArguments(dcp, '{"type":"script","target":"test"}', true, true);
     testArguments(dcp, '{"type":"script","target":"test"}', true, true);
diff --git a/test/mjsunit/deopt-with-outer-context.js b/test/mjsunit/deopt-with-outer-context.js
new file mode 100644
index 0000000..42a829d
--- /dev/null
+++ b/test/mjsunit/deopt-with-outer-context.js
@@ -0,0 +1,22 @@
+// 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 outer(y) {
+  function inner() {
+    var x = 10;
+    (function() {
+       // Access x from inner function to force it to be context allocated.
+       x = 20;
+       %DeoptimizeFunction(inner);
+    })();
+    // Variable y should be read from the outer context.
+    return y;
+  };
+  %OptimizeFunctionOnNextCall(inner);
+  return inner();
+}
+
+assertEquals(30, outer(30));
diff --git a/test/mjsunit/harmony/array-concat.js b/test/mjsunit/es6/array-concat.js
similarity index 97%
rename from test/mjsunit/harmony/array-concat.js
rename to test/mjsunit/es6/array-concat.js
index cabdf2d..bc9e1a0 100644
--- a/test/mjsunit/harmony/array-concat.js
+++ b/test/mjsunit/es6/array-concat.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-concat-spreadable --harmony-proxies --harmony-reflect
+// Flags: --harmony-proxies --harmony-reflect
 
 (function testArrayConcatArity() {
   "use strict";
@@ -267,30 +267,22 @@
 }
 
 (function testConcatSmallTypedArray() {
-  var max = [Math.pow(2, 8), Math.pow(2, 16), Math.pow(2, 32), false, false];
-  [
-    Uint8Array,
-    Uint16Array,
-    Uint32Array,
-    Float32Array,
-    Float64Array
-  ].forEach(function(ctor, i) {
-    testConcatTypedArray(ctor, 1, max[i]);
-  });
+  var length = 1;
+  testConcatTypedArray(Uint8Array, length, Math.pow(2, 8));
+  testConcatTypedArray(Uint16Array, length, Math.pow(2, 16));
+  testConcatTypedArray(Uint32Array, length,  Math.pow(2, 32));
+  testConcatTypedArray(Float32Array, length, false);
+  testConcatTypedArray(Float64Array, length, false);
 })();
 
 
 (function testConcatLargeTypedArray() {
-  var max = [Math.pow(2, 8), Math.pow(2, 16), Math.pow(2, 32), false, false];
-  [
-    Uint8Array,
-    Uint16Array,
-    Uint32Array,
-    Float32Array,
-    Float64Array
-  ].forEach(function(ctor, i) {
-    testConcatTypedArray(ctor, 4000, max[i]);
-  });
+  var length = 4000;
+  testConcatTypedArray(Uint8Array, length, Math.pow(2, 8));
+  testConcatTypedArray(Uint16Array, length, Math.pow(2, 16));
+  testConcatTypedArray(Uint32Array, length,  Math.pow(2, 32));
+  testConcatTypedArray(Float32Array, length, false);
+  testConcatTypedArray(Float64Array, length, false);
 })();
 
 
diff --git a/test/mjsunit/es6/array-length.js b/test/mjsunit/es6/array-length.js
index cc3b881..06efe00 100644
--- a/test/mjsunit/es6/array-length.js
+++ b/test/mjsunit/es6/array-length.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-tolength
-
 // Test array functions do not cause infinite loops when length is negative,
 // max_value, etc.
 
diff --git a/test/mjsunit/es6/block-for.js b/test/mjsunit/es6/block-for.js
index c7a23e8..d953d37 100644
--- a/test/mjsunit/es6/block-for.js
+++ b/test/mjsunit/es6/block-for.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: --harmony-completion
-
 "use strict";
 
 function props(x) {
diff --git a/test/mjsunit/es6/classes-super.js b/test/mjsunit/es6/classes-super.js
new file mode 100644
index 0000000..7bdf4ba
--- /dev/null
+++ b/test/mjsunit/es6/classes-super.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.
+
+"use strict";
+
+class Test {
+  m() {
+    super.length = 10;
+  }
+}
+
+var array = [];
+Test.prototype.m.call(array);
+assertEquals(10, array.length);
diff --git a/test/mjsunit/harmony/completion.js b/test/mjsunit/es6/completion.js
similarity index 98%
rename from test/mjsunit/harmony/completion.js
rename to test/mjsunit/es6/completion.js
index ceeafb2..05565bf 100644
--- a/test/mjsunit/harmony/completion.js
+++ b/test/mjsunit/es6/completion.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-completion --harmony-sloppy-let --no-legacy-const
+// Flags: --harmony-sloppy-let --no-legacy-const
 
 
 function assertUndef(x) {
diff --git a/test/mjsunit/es6/generators-iteration.js b/test/mjsunit/es6/generators-iteration.js
index faeb683..ae4c682 100644
--- a/test/mjsunit/es6/generators-iteration.js
+++ b/test/mjsunit/es6/generators-iteration.js
@@ -101,9 +101,9 @@
   testThrow(function*() { return yield* g(); });
 
   if (g instanceof GeneratorFunction) {
-    testNext(function() { return new g(); });
-    testSend(function() { return new g(); });
-    testThrow(function() { return new g(); });
+    testNext(g);
+    testSend(g);
+    testThrow(g);
   }
 }
 
@@ -259,18 +259,6 @@
     [1, 2, undefined]);
 
 TestGenerator(
-    function g18() {
-      function* g() { yield this.x; yield this.y; }
-      var iter = new g;
-      iter.x = 1;
-      iter.y = 2;
-      return iter;
-    },
-    [1, 2, undefined],
-    "foo",
-    [1, 2, undefined]);
-
-TestGenerator(
     function* g19() {
       var x = 1;
       yield x;
@@ -409,39 +397,17 @@
     "foo",
     [42, undefined]);
 
-// Test that yield* re-yields received results without re-boxing.
-function TestDelegatingYield() {
-  function results(results) {
-    var i = 0;
-    function next() {
-      return results[i++];
-    }
-    var iter = { next: next };
-    var ret = {};
-    ret[Symbol.iterator] = function() { return iter; };
-    return ret;
-  }
-  function* yield_results(expected) {
-    return yield* results(expected);
-  }
-  function collect_results(iterable) {
-    var iter = iterable[Symbol.iterator]();
-    var ret = [];
-    var result;
-    do {
-      result = iter.next();
-      ret.push(result);
-    } while (!result.done);
-    return ret;
-  }
-  // We have to put a full result for the end, because the return will re-box.
-  var expected = [{value: 1}, 13, "foo", {value: 34, done: true}];
-
-  // Sanity check.
-  assertEquals(expected, collect_results(results(expected)));
-  assertEquals(expected, collect_results(yield_results(expected)));
+// Test that yield* validates iterator results.
+function TestDelegatingYield(junk) {
+  var iterator = {next: () => junk};
+  var iterable = {[Symbol.iterator]: () => iterator};
+  function* g() { return yield* iterable };
+  assertThrows(() => g().next(), TypeError);
 }
 TestDelegatingYield();
+TestDelegatingYield(null);
+TestDelegatingYield(42);
+TestDelegatingYield(true);
 
 function TestTryCatch(instantiate) {
   function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; }
@@ -693,3 +659,16 @@
   assertThrows(TestThrowRecursion, Error);
 }
 TestRecursion();
+
+
+// Test yield* on non-iterable objects.
+function* g(junk) { return yield* junk }
+var non_iterables = [
+  42,
+  {[Symbol.iterator]: 42},
+  {[Symbol.iterator]: () => 42},
+  {[Symbol.iterator]: () => ({next: 42})},
+];
+for (let junk of non_iterables) {
+  assertThrows(() => g(junk).next(), TypeError);
+}
diff --git a/test/mjsunit/es6/generators-objects.js b/test/mjsunit/es6/generators-objects.js
index 9390776..f304738 100644
--- a/test/mjsunit/es6/generators-objects.js
+++ b/test/mjsunit/es6/generators-objects.js
@@ -59,18 +59,12 @@
   assertEquals("[object Generator]", String(iter));
   assertEquals([], Object.getOwnPropertyNames(iter));
   assertTrue(iter !== g());
-
-  // g() is the same as new g().
-  iter = new g();
-  assertSame(g.prototype, Object.getPrototypeOf(iter));
-  assertTrue(iter instanceof g);
-  assertEquals("Generator", %_ClassOf(iter));
-  assertEquals("[object Generator]", String(iter));
   assertEquals("[object Generator]", Object.prototype.toString.call(iter));
   var gf = iter.__proto__.constructor;
   assertEquals("[object GeneratorFunction]", Object.prototype.toString.call(gf));
-  assertEquals([], Object.getOwnPropertyNames(iter));
-  assertTrue(iter !== new g());
+
+  // generators are not constructable.
+  assertThrows(()=>new g());
 }
 TestGeneratorObject();
 
diff --git a/test/mjsunit/es6/generators-runtime.js b/test/mjsunit/es6/generators-runtime.js
index 98015b7..5c426b2 100644
--- a/test/mjsunit/es6/generators-runtime.js
+++ b/test/mjsunit/es6/generators-runtime.js
@@ -99,7 +99,7 @@
   assertSame(GeneratorObjectPrototype,
              Object.getPrototypeOf((function*(){yield 1}).prototype));
 
-  var expected_property_names = ["next", "throw", "constructor"];
+  var expected_property_names = ["next", "return", "throw", "constructor"];
   var found_property_names =
       Object.getOwnPropertyNames(GeneratorObjectPrototype);
 
diff --git a/test/mjsunit/es6/generators-states.js b/test/mjsunit/es6/generators-states.js
index 0a2173a..4e8c580 100644
--- a/test/mjsunit/es6/generators-states.js
+++ b/test/mjsunit/es6/generators-states.js
@@ -25,6 +25,7 @@
 // Throw on a suspendedStart iterator.
 iter = nextGenerator();
 assertThrows(function() { iter.throw(new Foo) }, Foo)
+assertIteratorIsClosed(iter);
 assertThrows(function() { iter.throw(new Foo) }, Foo)
 assertIteratorIsClosed(iter);
 
@@ -65,3 +66,29 @@
 assertIteratorResult(3, false, iter.next());
 assertIteratorResult(4, false, iter.next());
 assertIteratorIsClosed(iter);
+
+
+// A return that doesn't close.
+{
+  let g = function*() { try {return 42} finally {yield 43} };
+
+  let x = g();
+  assertEquals({value: 43, done: false}, x.next());
+  assertEquals({value: 42, done: true}, x.next());
+}
+{
+  let x;
+  let g = function*() { try {return 42} finally {x.throw(666)} };
+
+  x = g();
+  assertThrows(() => x.next(), TypeError);  // Still executing.
+}
+{
+  let x;
+  let g = function*() {
+    try {return 42} finally {try {x.throw(666)} catch(e) {}}
+  };
+
+  x = g();
+  assertEquals({value: 42, done: true}, x.next());
+}
diff --git a/test/mjsunit/es6/hasinstance-symbol.js b/test/mjsunit/es6/hasinstance-symbol.js
new file mode 100644
index 0000000..6783d8d
--- /dev/null
+++ b/test/mjsunit/es6/hasinstance-symbol.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.
+
+// Verify that the hasInstance symbol is installed on function prototype.
+// Test262 makes deeper tests.
+
+(function TestHasInstance() {
+  var a = Array();
+  assertTrue(Array[Symbol.hasInstance](a));
+  assertFalse(Function.prototype[Symbol.hasInstance].call());
+})();
diff --git a/test/mjsunit/es6/no-unicode-regexp-flag.js b/test/mjsunit/es6/no-unicode-regexp-flag.js
index b56a4b5..035627c 100644
--- a/test/mjsunit/es6/no-unicode-regexp-flag.js
+++ b/test/mjsunit/es6/no-unicode-regexp-flag.js
@@ -7,7 +7,7 @@
 // mjsunit/es6/regexp-flags tests that the property is there when the
 // flag is on.
 
-// Flags: --harmony-regexp
+// Flags: --harmony-regexps --no-harmony-unicode-regexps
 
 'use strict';
 
diff --git a/test/mjsunit/es6/object-assign.js b/test/mjsunit/es6/object-assign.js
index d56cb0d..1fec766 100644
--- a/test/mjsunit/es6/object-assign.js
+++ b/test/mjsunit/es6/object-assign.js
@@ -138,3 +138,36 @@
   assertThrows(function() { return Object.assign(target, source); }, ErrorB);
   assertEquals(log, "b");
 })();
+
+(function add_to_source() {
+  var target = {set k1(v) { source.k3 = 100; }};
+  var source = {k1:10};
+  Object.defineProperty(source, "k2",
+      {value: 20, enumerable: false, configurable: true});
+  Object.assign(target, source);
+  assertEquals(undefined, target.k2);
+  assertEquals(undefined, target.k3);
+})();
+
+(function reconfigure_enumerable_source() {
+  var target = {set k1(v) {
+    Object.defineProperty(source, "k2", {value: 20, enumerable: true});
+  }};
+  var source = {k1:10};
+  Object.defineProperty(source, "k2",
+      {value: 20, enumerable: false, configurable: true});
+  Object.assign(target, source);
+  assertEquals(20, target.k2);
+})();
+
+(function propagate_assign_failure() {
+  var target = {set k1(v) { throw "fail" }};
+  var source = {k1:10};
+  assertThrows(()=>Object.assign(target, source));
+})();
+
+(function propagate_read_failure() {
+  var target = {};
+  var source = {get k1() { throw "fail" }};
+  assertThrows(()=>Object.assign(target, source));
+})();
diff --git a/test/mjsunit/es6/object-literals-method.js b/test/mjsunit/es6/object-literals-method.js
index e4527cb..90bc51e 100644
--- a/test/mjsunit/es6/object-literals-method.js
+++ b/test/mjsunit/es6/object-literals-method.js
@@ -239,16 +239,14 @@
 })();
 
 
-(function TestGeneratorConstructable() {
+(function TestGeneratorNotConstructable() {
   var object = {
     *method() {
       yield 1;
     }
   };
 
-  var g = new object.method();
-  assertIteratorResult(1, false, g.next());
-  assertIteratorResult(undefined, true, g.next());
+  assertThrows(()=>new object.method());
 })();
 
 
diff --git a/test/mjsunit/es6/regexp-tolength.js b/test/mjsunit/es6/regexp-tolength.js
index d9e967b..f7cfe92 100644
--- a/test/mjsunit/es6/regexp-tolength.js
+++ b/test/mjsunit/es6/regexp-tolength.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-tolength
-
 'use strict';
 
 let regexp = /x/g;
diff --git a/test/mjsunit/es6/regexp-tostring.js b/test/mjsunit/es6/regexp-tostring.js
new file mode 100644
index 0000000..3deeeb7
--- /dev/null
+++ b/test/mjsunit/es6/regexp-tostring.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.
+
+var log = [];
+
+var fake =
+    {
+      get source() {
+        log.push("p");
+        return {
+          toString: function() {
+            log.push("ps");
+            return "pattern";
+          }
+        };
+      },
+      get flags() {
+        log.push("f");
+        return {
+          toString: function() {
+            log.push("fs");
+            return "flags";
+          }
+        };
+      }
+    }
+
+function testThrows(x) {
+  try {
+    RegExp.prototype.toString.call(x);
+  } catch (e) {
+    assertTrue(/incompatible receiver/.test(e.message));
+    return;
+  }
+  assertUnreachable();
+}
+
+testThrows(1);
+testThrows(null);
+Number.prototype.source = "a";
+Number.prototype.flags = "b";
+testThrows(1);
+
+assertEquals("/pattern/flags", RegExp.prototype.toString.call(fake));
+assertEquals(["p", "ps", "f", "fs"], log);
diff --git a/test/mjsunit/es6/regress/regress-594084.js b/test/mjsunit/es6/regress/regress-594084.js
new file mode 100644
index 0000000..4953cc9
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-594084.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: --lazy --min-preparse-length=0
+(function() {
+  function CRASH(defaultParameter =
+      (function() { function functionDeclaration() { return 0; } }())) {
+  }
+})();
diff --git a/test/mjsunit/es6/symbols.js b/test/mjsunit/es6/symbols.js
index d502a83..3833857 100644
--- a/test/mjsunit/es6/symbols.js
+++ b/test/mjsunit/es6/symbols.js
@@ -441,8 +441,9 @@
 
 function TestWellKnown() {
   var symbols = [
+    "hasInstance",
     // TODO(rossberg): reactivate once implemented.
-    // "hasInstance", "isConcatSpreadable", "isRegExp",
+    // "isConcatSpreadable", "isRegExp",
     "iterator", /* "toStringTag", */ "unscopables"
   ]
 
diff --git a/test/mjsunit/es6/tail-call-megatest.js b/test/mjsunit/es6/tail-call-megatest.js
new file mode 100644
index 0000000..0057961
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-megatest.js
@@ -0,0 +1,292 @@
+// Copyright 2016 the V8 project 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-tailcalls --no-turbo-inlining
+
+
+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 CheckArguments(expected, args) {
+  args = Array.prototype.slice.call(args);
+  assertEquals(expected, args);
+}
+%NeverOptimizeFunction(CheckArguments);
+
+
+var CAN_INLINE_COMMENT  = "// Let it be inlined.";
+var DONT_INLINE_COMMENT = (function() {
+  var line = "// Don't inline. Don't inline. Don't inline. Don't inline.";
+  for (var i = 0; i < 4; i++) {
+    line += "\n  " + line;
+  }
+  return line;
+})();
+
+
+function ident_source(source, ident) {
+  ident = " ".repeat(ident);
+  return ident + source.replace(/\n/gi, "\n" + ident);
+}
+
+var global = Function('return this')();
+var the_receiver = {receiver: 1};
+
+function run_tests() {
+  function inlinable_comment(inlinable) {
+    return inlinable ? CAN_INLINE_COMMENT : DONT_INLINE_COMMENT;
+  }
+
+  var f_cfg_sloppy = {
+    func_name: 'f',
+    source_template: function(cfg) {
+      var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
+                                                 : "global";
+      var lines = [
+        `function f(a) {`,
+        `  ${inlinable_comment(cfg.f_inlinable)}`,
+        `  assertEquals(${receiver}, this);`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  %DeoptimizeNow();`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  return 42;`,
+        `}`,
+      ];
+      return lines.join("\n");
+    },
+  };
+
+  var f_cfg_strict = {
+    func_name: 'f',
+    source_template: function(cfg) {
+      var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
+                                                 : "undefined";
+      var lines = [
+        `function f(a) {`,
+        `  "use strict";`,
+        `  ${inlinable_comment(cfg.f_inlinable)}`,
+        `  assertEquals(${receiver}, this);`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  %DeoptimizeNow();`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  return 42;`,
+        `}`,
+      ];
+      return lines.join("\n");
+    },
+  };
+
+  var f_cfg_possibly_eval = {
+    func_name: 'eval',
+    source_template: function(cfg) {
+      var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
+                                                 : "global";
+      var lines = [
+        `function f(a) {`,
+        `  ${inlinable_comment(cfg.f_inlinable)}`,
+        `  assertEquals(${receiver}, this);`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  %DeoptimizeNow();`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  return 42;`,
+        `}`,
+        `var eval = f;`,
+      ];
+      return lines.join("\n");
+    },
+  };
+
+  var f_cfg_bound = {
+    func_name: 'bound',
+    source_template: function(cfg) {
+      var lines = [
+        `function f(a) {`,
+        `  "use strict";`,
+        `  ${inlinable_comment(cfg.f_inlinable)}`,
+        `  assertEquals(receiver, this);`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  %DeoptimizeNow();`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  return 42;`,
+        `}`,
+        `var receiver = {a: 153};`,
+        `var bound = f.bind(receiver);`,
+      ];
+      return lines.join("\n");
+    },
+  };
+
+  var f_cfg_proxy = {
+    func_name: 'p',
+    source_template: function(cfg) {
+      var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
+                                                 : "global";
+      var lines = [
+        `function f(a) {`,
+        `  ${inlinable_comment(cfg.f_inlinable)}`,
+        `  assertEquals(${receiver}, this);`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  %DeoptimizeNow();`,
+        `  CheckArguments([${cfg.f_args}], arguments);`,
+        `  CheckStackTrace([f, test]);`,
+        `  return 42;`,
+        `}`,
+        `var p = new Proxy(f, {});`,
+      ];
+      return lines.join("\n");
+    },
+  };
+
+  var g_cfg_normal = {
+    receiver: undefined,
+    source_template: function(cfg) {
+      var lines = [
+        `function g(a) {`,
+        `  "use strict";`,
+        `  ${inlinable_comment(cfg.g_inlinable)}`,
+        `  CheckArguments([${cfg.g_args}], arguments);`,
+        `  return ${cfg.f_name}(${cfg.f_args});`,
+        `}`,
+      ];
+      return lines.join("\n");
+    },
+  };
+
+
+  var g_cfg_function_apply = {
+    receiver: "the_receiver",
+    source_template: function(cfg) {
+      var lines = [
+        `function g(a) {`,
+        `  "use strict";`,
+        `  ${inlinable_comment(cfg.g_inlinable)}`,
+        `  CheckArguments([${cfg.g_args}], arguments);`,
+        `  return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`,
+        `}`,
+      ];
+      return lines.join("\n");
+    },
+  };
+
+
+  var g_cfg_function_call = {
+    receiver: "the_receiver",
+    source_template: function(cfg) {
+      var f_args = "the_receiver";
+      if (cfg.f_args !== "") f_args += ", ";
+      f_args += cfg.f_args;
+
+      var lines = [
+        `function g(a) {`,
+        `  "use strict";`,
+        `  ${inlinable_comment(cfg.g_inlinable)}`,
+        `  CheckArguments([${cfg.g_args}], arguments);`,
+        `  return ${cfg.f_name}.call(${f_args});`,
+        `}`,
+      ];
+      return lines.join("\n");
+    },
+  };
+
+
+  function test_template(cfg) {
+    var f_source = cfg.f_source_template(cfg);
+    var g_source = cfg.g_source_template(cfg);
+    f_source = ident_source(f_source, 2);
+    g_source = ident_source(g_source, 2);
+
+    var lines = [
+      `(function() {`,
+      f_source,
+      g_source,
+      `  function test() {`,
+      `    "use strict";`,
+      `    assertEquals(42, g(${cfg.g_args}));`,
+      `  }`,
+      `  ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : ""};`,
+      `  ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : ""};`,
+      ``,
+      `  test();`,
+      `  %OptimizeFunctionOnNextCall(test);`,
+      `  %OptimizeFunctionOnNextCall(f);`,
+      `  %OptimizeFunctionOnNextCall(g);`,
+      `  test();`,
+      `})();`,
+      ``,
+    ];
+    var source = lines.join("\n");
+    return source;
+  }
+
+  // TODO(v8:4698), TODO(ishell): support all commented cases.
+  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];
+  var f_variants = [
+      f_cfg_sloppy,
+      f_cfg_strict,
+      f_cfg_bound,
+      f_cfg_proxy,
+      f_cfg_possibly_eval,
+  ];
+  var g_variants = [
+      g_cfg_normal,
+      g_cfg_function_call,
+      g_cfg_function_apply,
+  ];
+
+  f_variants.forEach((f_cfg) => {
+    g_variants.forEach((g_cfg) => {
+      f_args_variants.forEach((f_args) => {
+        g_args_variants.forEach((g_args) => {
+          f_inlinable_variants.forEach((f_inlinable) => {
+            g_inlinable_variants.forEach((g_inlinable) => {
+              var cfg = {
+                f_source_template: f_cfg.source_template,
+                f_inlinable,
+                f_args,
+                f_name: f_cfg.func_name,
+                f_receiver: g_cfg.receiver,
+                g_source_template: g_cfg.source_template,
+                g_inlinable,
+                g_args,
+              };
+              var source = test_template(cfg);
+              print("====================");
+              print(source);
+              eval(source);
+            });
+          });
+        });
+      });
+    });
+  });
+}
+
+run_tests();
diff --git a/test/mjsunit/es6/tail-call-proxies.js b/test/mjsunit/es6/tail-call-proxies.js
new file mode 100644
index 0000000..25f9fcf
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-proxies.js
@@ -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.
+
+// Flags: --allow-natives-syntax --harmony-tailcalls --harmony-proxies
+"use strict";
+
+Error.prepareStackTrace = (e,s) => s;
+
+function CheckStackTrace(expected) {
+  var stack = (new Error()).stack;
+  assertEquals("CheckStackTrace", stack[0].getFunctionName());
+  for (var i = 0; i < expected.length; i++) {
+    assertEquals(expected[i].name, stack[i + 1].getFunctionName());
+  }
+}
+
+
+// Tail call proxy function when caller does not have an arguments
+// adaptor frame.
+(function test() {
+  // Caller and callee have same number of arguments.
+  function f1(a) {
+    CheckStackTrace([f1, test]);
+    return 10 + a;
+  }
+  var p1 = new Proxy(f1, {});
+  function g1(a) { return p1(2); }
+  assertEquals(12, g1(1));
+
+  // Caller has more arguments than callee.
+  function f2(a) {
+    CheckStackTrace([f2, test]);
+    return 10 + a;
+  }
+  var p2 = new Proxy(f2, {});
+  function g2(a, b, c) { return p2(2); }
+  assertEquals(12, g2(1, 2, 3));
+
+  // Caller has less arguments than callee.
+  function f3(a, b, c) {
+    CheckStackTrace([f3, test]);
+    return 10 + a + b + c;
+  }
+  var p3 = new Proxy(f3, {});
+  function g3(a) { return p3(2, 3, 4); }
+  assertEquals(19, g3(1));
+
+  // Callee has arguments adaptor frame.
+  function f4(a, b, c) {
+    CheckStackTrace([f4, test]);
+    return 10 + a;
+  }
+  var p4 = new Proxy(f4, {});
+  function g4(a) { return p4(2); }
+  assertEquals(12, g4(1));
+})();
+
+
+// Tail call proxy function when caller has an arguments adaptor frame.
+(function test() {
+  // Caller and callee have same number of arguments.
+  function f1(a) {
+    CheckStackTrace([f1, test]);
+    return 10 + a;
+  }
+  var p1 = new Proxy(f1, {});
+  function g1(a) { return p1(2); }
+  assertEquals(12, g1());
+
+  // Caller has more arguments than callee.
+  function f2(a) {
+    CheckStackTrace([f2, test]);
+    return 10 + a;
+  }
+  var p2 = new Proxy(f2, {});
+  function g2(a, b, c) { return p2(2); }
+  assertEquals(12, g2());
+
+  // Caller has less arguments than callee.
+  function f3(a, b, c) {
+    CheckStackTrace([f3, test]);
+    return 10 + a + b + c;
+  }
+  var p3 = new Proxy(f3, {});
+  function g3(a) { return p3(2, 3, 4); }
+  assertEquals(19, g3());
+
+  // Callee has arguments adaptor frame.
+  function f4(a, b, c) {
+    CheckStackTrace([f4, test]);
+    return 10 + a;
+  }
+  var p4 = new Proxy(f4, {});
+  function g4(a) { return p4(2); }
+  assertEquals(12, g4());
+})();
diff --git a/test/mjsunit/es6/tail-call-simple.js b/test/mjsunit/es6/tail-call-simple.js
new file mode 100644
index 0000000..d2890b0
--- /dev/null
+++ b/test/mjsunit/es6/tail-call-simple.js
@@ -0,0 +1,107 @@
+// Copyright 2016 the V8 project 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-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 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 g(n - 1);
+  }
+  function g(n){
+    if (n <= 0) {
+      return "bar";
+    }
+    return f(n - 1);
+  }
+  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 f_bound(n - 1);
+  }
+  var f_bound = f0.bind({});
+  function f(n) {
+    return 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 g_bound(n - 1);
+  }
+  function g0(n){
+    if (n <= 0) {
+      return "bar";
+    }
+    return f_bound(n - 1);
+  }
+  var f_bound = f0.bind({});
+  var g_bound = g0.bind({});
+  function f(n) {
+    return 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/es6/tail-call.js b/test/mjsunit/es6/tail-call.js
new file mode 100644
index 0000000..e9539c3
--- /dev/null
+++ b/test/mjsunit/es6/tail-call.js
@@ -0,0 +1,386 @@
+// Copyright 2016 the V8 project 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-tailcalls
+"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());
+  }
+}
+
+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 f1(2); }
+
+  // Caller has more arguments than callee.
+  function f2(a) {
+    CheckStackTrace([f2, test]);
+    return 10 + a;
+  }
+  function g2(a, b, c) { return 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 f3(2, 3, 4); }
+
+  // Callee has arguments adaptor frame.
+  function f4(a, b, c) {
+    CheckStackTrace([f4, test]);
+    return 10 + a;
+  }
+  function g4(a) { return f4(2); }
+
+  function test() {
+    assertEquals(12, g1(1));
+    assertEquals(12, g2(1, 2, 3));
+    assertEquals(19, g3(1));
+    assertEquals(12, g4(1));
+  }
+  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 f1(2); }
+
+  // Caller has more arguments than callee.
+  function f2(a) {
+    CheckStackTrace([f2, test]);
+    return 10 + a;
+  }
+  function g2(a, b, c) { return 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 f3(2, 3, 4); }
+
+  // Callee has arguments adaptor frame.
+  function f4(a, b, c) {
+    CheckStackTrace([f4, test]);
+    return 10 + a;
+  }
+  function g4(a) { return f4(2); }
+
+  function test() {
+    assertEquals(12, g1());
+    assertEquals(12, g2());
+    assertEquals(19, g3());
+    assertEquals(12, g4());
+  }
+  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 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 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 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 b4(2); }
+
+  function test() {
+    assertEquals(12, g1(1));
+    assertEquals(12, g2(1, 2, 3));
+    assertEquals(19, g3(1));
+    assertEquals(12, g4(1));
+  }
+  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 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 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 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 b4(2); }
+
+  function test() {
+    assertEquals(12, g1());
+    assertEquals(12, g2());
+    assertEquals(19, g3());
+    assertEquals(12, g4());
+  }
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Tail calling via various expressions.
+(function() {
+  function g1(a) {
+    return f([f, g1, test], false) || f([f, test], true);
+  }
+
+  function g2(a) {
+    return f([f, g2, test], true) && f([f, test], true);
+  }
+
+  function g3(a) {
+    return f([f, g3, test], 13), f([f, test], 153);
+  }
+
+  function test() {
+    assertEquals(true, g1());
+    assertEquals(true, g2());
+    assertEquals(153, g3());
+  }
+  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 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 f_153([f_153, test]);
+  }
+
+  function test() {
+    assertEquals(153, tc1());
+    assertEquals(153, tc2());
+    assertEquals(153, tc3());
+  }
+  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 f_153([f_153, test]);
+    }
+  }
+
+  function tf3(a) {
+    try {
+      f_153([f_153, tf3, test]);
+    } finally {
+      f_153([f_153, tf3, test]);
+    }
+    return f_153([f_153, test]);
+  }
+
+  function test() {
+    assertEquals(153, tf1());
+    assertEquals(153, tf2());
+    assertEquals(153, tf3());
+  }
+  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 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 f_153([f_153, test]);
+  }
+
+  function test() {
+    assertEquals(153, tcf1());
+    assertEquals(153, tcf2());
+    assertEquals(153, tcf3());
+    assertEquals(153, tcf4());
+  }
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
diff --git a/test/mjsunit/es6/typedarray.js b/test/mjsunit/es6/typedarray.js
index c43ba1c..e6a949c 100644
--- a/test/mjsunit/es6/typedarray.js
+++ b/test/mjsunit/es6/typedarray.js
@@ -529,6 +529,8 @@
 
   assertThrows(function() { a.set(0); }, TypeError);
   assertThrows(function() { a.set(0, 1); }, TypeError);
+
+  assertEquals(1, a.set.length);
 }
 
 TestTypedArraySet();
@@ -672,7 +674,6 @@
 
   // error cases
   assertThrows(function() { new DataView(ab, -1); }, RangeError);
-  assertThrows(function() { new DataView(ab, 1, -1); }, RangeError);
   assertThrows(function() { new DataView(); }, TypeError);
   assertThrows(function() { new DataView([]); }, TypeError);
   assertThrows(function() { new DataView(ab, 257); }, RangeError);
@@ -693,6 +694,19 @@
   CheckProperty("buffer");
   CheckProperty("byteOffset");
   CheckProperty("byteLength");
+
+  function CheckGetSetLength(name) {
+    assertEquals(1, DataView.prototype["get" + name].length);
+    assertEquals(2, DataView.prototype["set" + name].length);
+  }
+  CheckGetSetLength("Int8");
+  CheckGetSetLength("Uint8");
+  CheckGetSetLength("Int16");
+  CheckGetSetLength("Uint16");
+  CheckGetSetLength("Int32");
+  CheckGetSetLength("Uint32");
+  CheckGetSetLength("Float32");
+  CheckGetSetLength("Float64");
 }
 
 
diff --git a/test/mjsunit/for-in-opt.js b/test/mjsunit/for-in-opt.js
index e458e1d..8f73539 100644
--- a/test/mjsunit/for-in-opt.js
+++ b/test/mjsunit/for-in-opt.js
@@ -28,13 +28,14 @@
 var deopt_enum = false;
 
 var handler = {
-  enumerate(target) {
+  ownKeys() {
     if (deopt_enum) {
       %DeoptimizeFunction(f2);
       deopt_enum = false;
     }
-    return keys[Symbol.iterator]();
+    return keys;
   },
+  getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }},
 
   has(target, k) {
     if (deopt_has) {
@@ -42,7 +43,7 @@
       deopt_has = false;
     }
     has_keys.push(k);
-    return {value: 10, configurable: true, writable: false, enumerable: true};
+    return true;
   }
 };
 
@@ -67,7 +68,7 @@
 check_f2();
 check_f2();
 
-// Test lazy deopt after GetPropertyNamesFast
+// Test lazy deopt after ForInEnumerate
 %OptimizeFunctionOnNextCall(f2);
 deopt_enum = true;
 check_f2();
@@ -136,14 +137,13 @@
 }
 
 var handler3 = {
-  enumerate(target) {
-    return ["a", "b"][Symbol.iterator]();
-  },
+  ownKeys() { return ["a", "b"] },
+  getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }},
 
   has(target, k) {
     if (k == "a") count++;
     if (x) %ScheduleBreak();
-    return {value: 10, configurable: true, writable: false, enumerable: true};
+    return true;
   }
 };
 
diff --git a/test/mjsunit/function-caller.js b/test/mjsunit/function-caller.js
index a2c54bb..84f3cbe 100644
--- a/test/mjsunit/function-caller.js
+++ b/test/mjsunit/function-caller.js
@@ -47,7 +47,8 @@
 eval('f(null)');
 
 // Check called from strict builtin functions.
-[null, null].sort(f);
+// [null, null].sort(f);  // Does not work because sort tail calls.
+[null].forEach(f, null);
 
 // Check called from sloppy builtin functions.
 "abel".replace(/b/g, function h() {
diff --git a/test/mjsunit/function-names.js b/test/mjsunit/function-names.js
index 5ed0b79..6df31b9 100644
--- a/test/mjsunit/function-names.js
+++ b/test/mjsunit/function-names.js
@@ -65,10 +65,11 @@
     "getTimezoneOffset", "setTime", "setMilliseconds",
     "setUTCMilliseconds", "setSeconds", "setUTCSeconds", "setMinutes",
     "setUTCMinutes", "setHours", "setUTCHours", "setDate", "setUTCDate",
-    "setMonth", "setUTCMonth", "setFullYear", "setUTCFullYear", "toGMTString",
+    "setMonth", "setUTCMonth", "setFullYear", "setUTCFullYear",
     "toUTCString", "getYear", "setYear"];
 
 TestFunctionNames(Date.prototype, datePrototypeFunctions);
+assertEquals(Date.prototype.toGMTString, Date.prototype.toUTCString);
 
 
 // Function.prototype functions.
diff --git a/test/mjsunit/harmony/array-species-constructor-delete.js b/test/mjsunit/harmony/array-species-constructor-delete.js
new file mode 100644
index 0000000..e61d0dd
--- /dev/null
+++ b/test/mjsunit/harmony/array-species-constructor-delete.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-species
+
+// 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;
+
+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
new file mode 100644
index 0000000..d4eeefa
--- /dev/null
+++ b/test/mjsunit/harmony/array-species-constructor.js
@@ -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.
+
+// Flags: --harmony-species
+
+// 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;
+
+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
new file mode 100644
index 0000000..bccf3a4
--- /dev/null
+++ b/test/mjsunit/harmony/array-species-delete.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-species
+
+// 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];
+
+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
new file mode 100644
index 0000000..b5c5c16
--- /dev/null
+++ b/test/mjsunit/harmony/array-species-modified.js
@@ -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.
+
+// Flags: --harmony-species
+
+// 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});
+
+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
new file mode 100644
index 0000000..8ea59bc
--- /dev/null
+++ b/test/mjsunit/harmony/array-species-parent-constructor.js
@@ -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.
+
+// Flags: --harmony-species
+
+// 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;
+
+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
new file mode 100644
index 0000000..077b3f5
--- /dev/null
+++ b/test/mjsunit/harmony/array-species-proto.js
@@ -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.
+
+// Flags: --harmony-species
+
+// 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;
+
+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
index 75a45aa..3cef50c 100644
--- a/test/mjsunit/harmony/array-species.js
+++ b/test/mjsunit/harmony/array-species.js
@@ -16,6 +16,8 @@
 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
 
@@ -27,6 +29,7 @@
 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
 
@@ -44,11 +47,15 @@
              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);
@@ -61,6 +68,9 @@
                  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
 
@@ -74,6 +84,7 @@
              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
 
@@ -100,6 +111,7 @@
 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
 
@@ -133,17 +145,22 @@
 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);
-// TODO(littledan): Should be 1
-assertEquals(2, count);
+assertEquals(1, count);
 assertArrayEquals([0], params);
 
 count = 0;
 params = undefined;
 assertEquals(MyObservedArray,
              new MyObservedArray().splice().constructor);
-// TODO(littledan): Should be 1
-assertEquals(2, count);
+assertEquals(1, count);
 assertArrayEquals([0], params);
 
 // @@species constructor can be a Proxy, and the realm access doesn't
diff --git a/test/mjsunit/harmony/block-for-sloppy.js b/test/mjsunit/harmony/block-for-sloppy.js
index e9e9605..051d2b1 100644
--- a/test/mjsunit/harmony/block-for-sloppy.js
+++ b/test/mjsunit/harmony/block-for-sloppy.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --no-legacy-const --harmony-sloppy --harmony-sloppy-let
-// Flags: --harmony-completion
 
 function props(x) {
   var array = [];
diff --git a/test/mjsunit/harmony/debug-stepin-proxies.js b/test/mjsunit/harmony/debug-stepin-proxies.js
index 0689801..8595f40 100644
--- a/test/mjsunit/harmony/debug-stepin-proxies.js
+++ b/test/mjsunit/harmony/debug-stepin-proxies.js
@@ -36,13 +36,6 @@
   set: function(target, name, value) {
     return false;                    // l
   },                                 // m
-  enumerate: function(target) {
-    function* keys() {               // n
-      yield "foo";                   // o
-      yield "bar";                   // p
-    }                                // q
-    return keys();                   // r
-  },                                 // s
 }
 
 var proxy = new Proxy(target, handler);
@@ -52,9 +45,6 @@
 var has = "step" in proxy;           // b
 var get = proxy.step;                // c
 proxy.step = 43;                     // d
-for (var i in proxy) {               // e
-  log.push(i);                       // f
-}
 
 Debug.setListener(null);             // g
 
@@ -67,12 +57,5 @@
   "b0", "h4b20", "i2b20",                           // [[Has]]
   "c0", "j4c15", "k2c15",                           // [[Get]]
   "d0", "l4d11", "m2d11",                           // [[Set]]
-  "e14", "r4e14", "q4r11e14", "s2e14",              // for-in [[Enumerate]]
-      "o6e14", "q4e14", "p6e14", "q4e14", "q4e14",  // exhaust iterator
-  "e9",                                             // for-in-body
-      "h4e9","i2e9",                                // [[Has]] property
-  "f2","foo", "e9",                                 // for-in-body
-    "h4e9","i2e9",                                  // [[Has]]property
-  "f2","bar", "e9",                                 // for-in-body
   "g0"
 ], log);
diff --git a/test/mjsunit/harmony/destructuring.js b/test/mjsunit/harmony/destructuring.js
index 50f2785..e84abd1 100644
--- a/test/mjsunit/harmony/destructuring.js
+++ b/test/mjsunit/harmony/destructuring.js
@@ -263,6 +263,63 @@
 }());
 
 
+(function TestAssignmentExprInInitializers() {
+  {
+    let x, y;
+    {
+      let { x = y = 1 } = {};
+      assertSame(x, 1);
+      assertSame(y, 1);
+    }
+    assertSame(undefined, x);
+    assertSame(1, y);
+  }
+
+  {
+    let x, y;
+    {
+      let { x: x = y = 1 } = {};
+      assertSame(1, x);
+      assertSame(1, y);
+    }
+    assertSame(undefined, x);
+    assertSame(1, y);
+  }
+
+  {
+    let x, y;
+    {
+      let [ x = y = 1 ] = [];
+      assertSame(1, x);
+      assertSame(1, y);
+    }
+    assertSame(undefined, x);
+    assertSame(1, y);
+  }
+
+  {
+    let x, y;
+    (function({ x = y = 1 }) {}({}));
+    assertSame(undefined, x);
+    assertSame(1, y);
+  }
+
+  {
+    let x, y;
+    (function({ x: x = y = 1 }) {}({}));
+    assertSame(undefined, x);
+    assertSame(1, y);
+  }
+
+  {
+    let x, y;
+    (function([ x = y = 1 ]) {}([]));
+    assertSame(undefined, x);
+    assertSame(1, y);
+  }
+}());
+
+
 (function TestMultipleAccesses() {
   assertThrows(
     "'use strict';"+
@@ -1061,8 +1118,8 @@
 
 
 (function TestForInOfTDZ() {
-  assertThrows("'use strict'; let x = {}; for (let [x, y] of {x});", ReferenceError);
-  assertThrows("'use strict'; let x = {}; for (let [y, x] of {x});", ReferenceError);
+  assertThrows("'use strict'; let x = {}; for (let [x, y] of [x]);", ReferenceError);
+  assertThrows("'use strict'; let x = {}; for (let [y, x] of [x]);", ReferenceError);
   assertThrows("'use strict'; let x = {}; for (let [x, y] in {x});", ReferenceError);
   assertThrows("'use strict'; let x = {}; for (let [y, x] in {x});", ReferenceError);
 }());
diff --git a/test/mjsunit/harmony/do-expressions.js b/test/mjsunit/harmony/do-expressions.js
index e7e513a..3aace57 100644
--- a/test/mjsunit/harmony/do-expressions.js
+++ b/test/mjsunit/harmony/do-expressions.js
@@ -4,7 +4,6 @@
 
 // Flags: --harmony-do-expressions --harmony-sloppy-let --allow-natives-syntax
 // Flags: --harmony-default-parameters --harmony-destructuring-bind
-// Flags: --harmony-completion
 
 function returnValue(v) { return v; }
 function MyError() {}
diff --git a/test/mjsunit/harmony/function-name.js b/test/mjsunit/harmony/function-name.js
index 8ca5d82..7bb1f6a 100644
--- a/test/mjsunit/harmony/function-name.js
+++ b/test/mjsunit/harmony/function-name.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 //
 // Flags: --harmony-function-name
+// Flags: --harmony-destructuring-bind --harmony-destructuring-assignment
 
 (function testVariableDeclarationsFunction() {
   'use strict';
@@ -89,36 +90,59 @@
   assertEquals('set 44', descriptor.set.name);
 })();
 
-// TODO(adamk): Make computed property names work.
 (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) {},
   };
 
-  // Should be 'a'
-  assertEquals('', obj[a].name);
-  // Should be '[1]'
-  assertEquals('', obj[sym1].name);
+  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) { }
   }
 
-  // Should be 'a'
-  assertEquals('', C.prototype[a].name);
-  // Should be '[1]'
-  assertEquals('', C.prototype[sym1].name);
-  // Should be '[2]'
-  assertEquals('', C[sym2].name);
+  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);
 })();
 
 
@@ -159,3 +183,191 @@
   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
new file mode 100644
index 0000000..b3cd644
--- /dev/null
+++ b/test/mjsunit/harmony/function-sent.js
@@ -0,0 +1,90 @@
+// Copyright 2016 the V8 project 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-sent
+
+
+{
+  function* g() { return function.sent }
+  assertEquals({value: 42, done: true}, g().next(42));
+}
+
+
+{
+  function* g() {
+    try {
+      yield function.sent;
+    } finally {
+      yield function.sent;
+      return function.sent;
+    }
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, x.next(1));
+    assertEquals({value: 2, done: false}, x.next(2));
+    assertEquals({value: 3, done: true}, x.next(3));
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, x.next(1));
+    assertEquals({value: 2, done: false}, x.throw(2));
+    assertEquals({value: 3, done: true}, x.next(3));
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, x.next(1));
+    assertEquals({value: 2, done: false}, x.return(2));
+    assertEquals({value: 3, done: true}, x.next(3));
+  }
+}
+
+
+{
+  function* inner() {
+    try {
+      yield function.sent;
+    } finally {
+      return 666;
+    }
+  }
+
+  function* g() {
+    yield function.sent;
+    yield* inner();
+    return function.sent;
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, x.next(1));
+    assertEquals({value: undefined, done: false}, x.next(2));
+    assertEquals({value: 3, done: true}, x.next(3));
+  }
+
+  {
+    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.throw(42));
+  }
+
+  {
+    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));
+  }
+}
+
+
+assertThrows("function f() { return function.sent }", SyntaxError);
+assertThrows("() => { return function.sent }", SyntaxError);
+assertThrows("() => { function.sent }", SyntaxError);
+assertThrows("() => function.sent", SyntaxError);
+assertThrows("({*f() { function.sent }})", SyntaxError);
+assertDoesNotThrow("({*f() { return function.sent }})");
diff --git a/test/mjsunit/harmony/generators.js b/test/mjsunit/harmony/generators.js
new file mode 100644
index 0000000..5b04504
--- /dev/null
+++ b/test/mjsunit/harmony/generators.js
@@ -0,0 +1,252 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+{ // yield in try-catch
+
+  let g = function*() {
+    try {yield 1} catch (error) {assertEquals("caught", error)}
+  };
+
+  assertThrowsEquals(() => g().throw("not caught"), "not caught");
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, x.next());
+    assertEquals({value: undefined, done: true}, x.throw("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");
+  }
+}
+
+
+{ // return that doesn't close
+  let g = function*() { try {return 42} finally {yield 43} };
+
+  {
+    let x = g();
+    assertEquals({value: 43, done: false}, x.next());
+    assertEquals({value: 42, done: true}, x.next());
+  }
+}
+
+
+{ // return that doesn't close
+  let x;
+  let g = function*() { try {return 42} finally {x.throw(666)} };
+
+  {
+    x = g();
+    assertThrows(() => x.next(), 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}, x.return(666));
+    assertEquals({value: undefined, done: true}, x.next(42));
+    assertThrowsEquals(() => x.throw(43), 43);
+    assertEquals({value: 42, done: true}, x.return(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);
+  }
+
+  { // "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);
+  }
+
+  { // "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));
+  }
+
+  { // "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));
+  }
+}
+
+
+{ // 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}, x.return(666));
+    assertEquals({value: undefined, done: true}, x.next(42));
+    assertThrowsEquals(() => x.throw(43), 43);
+    assertEquals({value: 42, done: true}, x.return(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);
+  }
+
+  { // "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));
+  }
+
+  { // "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));
+  }
+
+  { // "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));
+  }
+}
+
+
+{ // 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}, 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));
+  }
+
+  {
+    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));
+  }
+}
+
+
+{ // 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}, 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));
+  }
+
+  {
+    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));
+  }
+}
+
+
+{ // 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}, 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());
+  }
+
+  {
+    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());
+  }
+
+  {
+    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());
+  }
+}
+
+
+{ // 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}, 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());
+  }
+
+  {
+    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: undefined, done: false}, x.next());
+    assertEquals({value: undefined, done: true}, x.next());
+  }
+
+  {
+    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);
+  }
+}
diff --git a/test/mjsunit/harmony/instanceof-es6.js b/test/mjsunit/harmony/instanceof-es6.js
new file mode 100644
index 0000000..60e7ee2
--- /dev/null
+++ b/test/mjsunit/harmony/instanceof-es6.js
@@ -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.
+
+// 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
new file mode 100644
index 0000000..94785de
--- /dev/null
+++ b/test/mjsunit/harmony/iterator-close.js
@@ -0,0 +1,364 @@
+// Copyright 2016 the V8 project 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 (let x of g()) { break; }
+  })());
+
+  assertEquals(undefined, (() => {
+    for (x of g()) { break; }
+  })());
+
+  assertThrowsEquals(() => {
+    for (let x of g()) { throw 42; }
+  }, 42);
+
+  assertThrowsEquals(() => {
+    for (x of g()) { throw 42; }
+  }, 42);
+
+  assertEquals(42, (() => {
+    for (let x of g()) { return 42; }
+  })());
+
+  assertEquals(42, (() => {
+    for (x of g()) { return 42; }
+  })());
+
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+}
+
+
+// Return method is not callable.
+{
+  g.prototype.return = 666;
+
+  assertThrows(() => {
+    for (let x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (let x of g()) { throw 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { throw 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (let x of g()) { return 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { return 666; }
+  }, TypeError);
+
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+}
+
+
+// Return method does not return an object.
+{
+  g.prototype.return = () => 666;
+
+  assertThrows(() => {
+    for (let x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (let x of g()) { throw 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { throw 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (let x of g()) { return 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { return 666; }
+  }, TypeError);
+
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+
+  assertEquals(42, eval('for (x of g()) { x; }'));
+}
+
+
+// Return method returns an object.
+{
+  let log = [];
+  g.prototype.return = (...args) => { log.push(args); return {} };
+
+  log = [];
+  for (let x of g()) { break; }
+  assertEquals([[]], log);
+
+  log = [];
+  for (x of g()) { break; }
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    for (let x of g()) { return 42; }
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    for (x of g()) { return 42; }
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, eval('for (x of g()) { x; }'));
+  assertEquals([], log);
+}
+
+
+// Return method throws.
+{
+  let log = [];
+  g.prototype.return = (...args) => { log.push(args); throw 23 };
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g()) { break; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (x of g()) { break; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g()) { return 42; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (x of g()) { return 42; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, eval('for (x of g()) { x; }'));
+  assertEquals([], log);
+}
+
+
+// Next method throws.
+{
+  g.prototype.next = () => { throw 666; };
+  g.prototype.return = () => { assertUnreachable() };
+
+  assertThrowsEquals(() => {
+    for (let x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (x of 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/object-entries.js b/test/mjsunit/harmony/object-entries.js
new file mode 100644
index 0000000..58af4d6
--- /dev/null
+++ b/test/mjsunit/harmony/object-entries.js
@@ -0,0 +1,249 @@
+// Copyright 2016 the V8 project 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-values-entries --harmony-proxies --harmony-reflect
+// Flags: --allow-natives-syntax
+
+function TestMeta() {
+  assertEquals(1, Object.entries.length);
+  assertEquals(Function.prototype, Object.getPrototypeOf(Object.entries));
+  assertEquals("entries", Object.entries.name);
+
+  var descriptor = Object.getOwnPropertyDescriptor(Object, "entries");
+  assertTrue(descriptor.writable);
+  assertFalse(descriptor.enumerable);
+  assertTrue(descriptor.configurable);
+
+  assertThrows(() => new Object.entries({}), TypeError);
+}
+TestMeta();
+
+
+function TestBasic() {
+  var x = 16;
+  var O = {
+    d: 1,
+    c: 3,
+    [Symbol.iterator]: void 0,
+    0: 123,
+    1000: 456,
+    [x * x]: "ducks",
+    [`0x${(x * x).toString(16)}`]: "quack"
+  };
+  O.a = 2;
+  O.b = 4;
+  Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
+  assertEquals([
+    ["0", 123],
+    ["256", "ducks"],
+    ["1000", 456],
+    ["d", 1],
+    ["c", 3],
+    ["0x100", "quack"],
+    ["a", 2],
+    ["b", 4]
+  ], Object.entries(O));
+  assertEquals(Object.entries(O), Object.keys(O).map(key => [key, O[key]]));
+
+  assertTrue(Array.isArray(Object.entries({})));
+  assertEquals(0, Object.entries({}).length);
+}
+TestBasic();
+
+
+function TestToObject() {
+  assertThrows(function() { Object.entries(); }, TypeError);
+  assertThrows(function() { Object.entries(null); }, TypeError);
+  assertThrows(function() { Object.entries(void 0); }, TypeError);
+}
+TestToObject();
+
+
+function TestOrder() {
+  var O = {
+    a: 1,
+    [Symbol.iterator]: null
+  };
+  O[456] = 123;
+  Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
+  var priv = %CreatePrivateSymbol("Secret");
+  O[priv] = 56;
+
+  var log = [];
+  var P = new Proxy(O, {
+    ownKeys(target) {
+      log.push("[[OwnPropertyKeys]]");
+      return Reflect.ownKeys(target);
+    },
+    get(target, name) {
+      log.push(`[[Get]](${JSON.stringify(name)})`);
+      return Reflect.get(target, name);
+    },
+    getOwnPropertyDescriptor(target, name) {
+      log.push(`[[GetOwnProperty]](${JSON.stringify(name)})`);
+      return Reflect.getOwnPropertyDescriptor(target, name);
+    },
+    set(target, name, value) {
+      assertUnreachable();
+    }
+  });
+
+  assertEquals([["456", 123], ["a", 1]], Object.entries(P));
+  assertEquals([
+    "[[OwnPropertyKeys]]",
+    "[[GetOwnProperty]](\"456\")",
+    "[[Get]](\"456\")",
+    "[[GetOwnProperty]](\"a\")",
+    "[[Get]](\"a\")",
+    "[[GetOwnProperty]](\"HIDDEN\")"
+  ], log);
+}
+TestOrder();
+
+
+function TestOrderWithDuplicates() {
+  var O = {
+    a: 1,
+    [Symbol.iterator]: null
+  };
+  O[456] = 123;
+  Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
+  var priv = %CreatePrivateSymbol("Secret");
+  O[priv] = 56;
+
+  var log = [];
+  var P = new Proxy(O, {
+    ownKeys(target) {
+      log.push("[[OwnPropertyKeys]]");
+      return ["a", Symbol.iterator, "a", "456", "HIDDEN", "HIDDEN", "456"];
+    },
+    get(target, name) {
+      log.push(`[[Get]](${JSON.stringify(name)})`);
+      return Reflect.get(target, name);
+    },
+    getOwnPropertyDescriptor(target, name) {
+      log.push(`[[GetOwnProperty]](${JSON.stringify(name)})`);
+      return Reflect.getOwnPropertyDescriptor(target, name);
+    },
+    set(target, name, value) {
+      assertUnreachable();
+    }
+  });
+
+  assertEquals([
+    ["a", 1],
+    ["a", 1],
+    ["456", 123],
+    ["456", 123]
+  ], Object.entries(P));
+  assertEquals([
+    "[[OwnPropertyKeys]]",
+    "[[GetOwnProperty]](\"a\")",
+    "[[Get]](\"a\")",
+    "[[GetOwnProperty]](\"a\")",
+    "[[Get]](\"a\")",
+    "[[GetOwnProperty]](\"456\")",
+    "[[Get]](\"456\")",
+    "[[GetOwnProperty]](\"HIDDEN\")",
+    "[[GetOwnProperty]](\"HIDDEN\")",
+    "[[GetOwnProperty]](\"456\")",
+    "[[Get]](\"456\")"
+  ], log);
+}
+TestOrderWithDuplicates();
+
+
+function TestPropertyFilter() {
+  var object = { prop3: 30 };
+  object[2] = 40;
+  object["prop4"] = 50;
+  Object.defineProperty(object, "prop5", { value: 60, enumerable: true });
+  Object.defineProperty(object, "prop6", { value: 70, enumerable: false });
+  Object.defineProperty(object, "prop7", {
+      enumerable: true, get() { return 80; }});
+  var sym = Symbol("prop8");
+  object[sym] = 90;
+
+  values = Object.entries(object);
+  assertEquals(5, values.length);
+  assertEquals([
+    [ "2", 40 ],
+    [ "prop3", 30 ],
+    [ "prop4", 50 ],
+    [ "prop5", 60 ],
+    [ "prop7", 80 ]
+  ], values);
+}
+TestPropertyFilter();
+
+
+function TestWithProxy() {
+  var obj1 = {prop1:10};
+  var proxy1 = new Proxy(obj1, { });
+  assertEquals([ [ "prop1", 10 ] ], Object.entries(proxy1));
+
+  var obj2 = {};
+  Object.defineProperty(obj2, "prop2", { value: 20, enumerable: true });
+  Object.defineProperty(obj2, "prop3", {
+      get() { return 30; }, enumerable: true });
+  var proxy2 = new Proxy(obj2, {
+    getOwnPropertyDescriptor(target, name) {
+      return Reflect.getOwnPropertyDescriptor(target, name);
+    }
+  });
+  assertEquals([ [ "prop2", 20 ], [ "prop3", 30 ] ], Object.entries(proxy2));
+
+  var obj3 = {};
+  var count = 0;
+  var proxy3 = new Proxy(obj3, {
+    get(target, property, receiver) {
+      return count++ * 5;
+    },
+    getOwnPropertyDescriptor(target, property) {
+      return { configurable: true, enumerable: true };
+    },
+    ownKeys(target) {
+      return [ "prop0", "prop1", Symbol("prop2"), Symbol("prop5") ];
+    }
+  });
+  assertEquals([ [ "prop0", 0 ], [ "prop1", 5 ] ], Object.entries(proxy3));
+}
+TestWithProxy();
+
+
+function TestMutateDuringEnumeration() {
+  var aDeletesB = {
+    get a() {
+      delete this.b;
+      return 1;
+    },
+    b: 2
+  };
+  assertEquals([ [ "a", 1 ] ], Object.entries(aDeletesB));
+
+  var aRemovesB = {
+    get a() {
+      Object.defineProperty(this, "b", { enumerable: false });
+      return 1;
+    },
+    b: 2
+  };
+  assertEquals([ [ "a", 1 ] ], Object.entries(aRemovesB));
+
+  var aAddsB = { get a() { this.b = 2; return 1; } };
+  assertEquals([ [ "a", 1 ] ], Object.entries(aAddsB));
+
+  var aMakesBEnumerable = {};
+  Object.defineProperty(aMakesBEnumerable, "a", {
+    get() {
+      Object.defineProperty(this, "b", { enumerable: true });
+      return 1;
+    },
+    enumerable: true
+  });
+  Object.defineProperty(aMakesBEnumerable, "b", {
+      value: 2, configurable:true, enumerable: false });
+  assertEquals([ [ "a", 1 ], [ "b", 2 ] ], Object.entries(aMakesBEnumerable));
+}
+TestMutateDuringEnumeration();
diff --git a/test/mjsunit/harmony/object-get-own-property-descriptors.js b/test/mjsunit/harmony/object-get-own-property-descriptors.js
new file mode 100644
index 0000000..b23e7d6
--- /dev/null
+++ b/test/mjsunit/harmony/object-get-own-property-descriptors.js
@@ -0,0 +1,206 @@
+// Copyright 2016 the V8 project 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-own-property-descriptors
+// Flags: --harmony-proxies --harmony-reflect --allow-natives-syntax
+
+function DataDescriptor(value) {
+  return { "enumerable": true, "configurable": true, "writable": true, value };
+}
+
+
+function TestMeta() {
+  assertEquals(1, Object.getOwnPropertyDescriptors.length);
+  assertEquals(Function.prototype,
+               Object.getPrototypeOf(Object.getOwnPropertyDescriptors));
+  assertEquals(
+      'getOwnPropertyDescriptors', Object.getOwnPropertyDescriptors.name);
+  var desc = Reflect.getOwnPropertyDescriptor(
+      Object, 'getOwnPropertyDescriptors');
+  assertFalse(desc.enumerable);
+  assertTrue(desc.writable);
+  assertTrue(desc.configurable);
+}
+TestMeta();
+
+
+function TestToObject() {
+  assertThrows(function() {
+    Object.getOwnPropertyDescriptors(null);
+  }, TypeError);
+
+  assertThrows(function() {
+    Object.getOwnPropertyDescriptors(undefined);
+  }, TypeError);
+
+  assertThrows(function() {
+    Object.getOwnPropertyDescriptors();
+  }, TypeError);
+}
+TestToObject();
+
+
+function TestPrototypeProperties() {
+  function F() {};
+  F.prototype.a = "A";
+  F.prototype.b = "B";
+
+  var F2 = new F();
+  Object.defineProperties(F2, {
+    "b": {
+      enumerable: false,
+      configurable: true,
+      writable: false,
+      value: "Shadowed 'B'"
+    },
+    "c": {
+      enumerable: false,
+      configurable: true,
+      writable: false,
+      value: "C"
+    }
+  });
+
+  assertEquals({
+    "b": {
+      enumerable: false,
+      configurable: true,
+      writable: false,
+      value: "Shadowed 'B'"
+    },
+    "c": {
+      enumerable: false,
+      configurable: true,
+      writable: false,
+      value: "C"
+    }
+  }, Object.getOwnPropertyDescriptors(F2));
+}
+TestPrototypeProperties();
+
+
+function TestPrototypeProperties() {
+  function F() {};
+  F.prototype.a = "A";
+  F.prototype.b = "B";
+
+  var F2 = new F();
+  Object.defineProperties(F2, {
+    "b": {
+      enumerable: false,
+      configurable: true,
+      writable: false,
+      value: "Shadowed 'B'"
+    },
+    "c": {
+      enumerable: false,
+      configurable: true,
+      writable: false,
+      value: "C"
+    }
+  });
+
+  assertEquals({
+    "b": {
+      enumerable: false,
+      configurable: true,
+      writable: false,
+      value: "Shadowed 'B'"
+    },
+    "c": {
+      enumerable: false,
+      configurable: true,
+      writable: false,
+      value: "C"
+    }
+  }, Object.getOwnPropertyDescriptors(F2));
+}
+TestPrototypeProperties();
+
+
+function TestTypeFilteringAndOrder() {
+  var log = [];
+  var sym = Symbol("foo");
+  var psym = %CreatePrivateSymbol("private");
+  var O = {
+    0: 0,
+    [sym]: 3,
+    "a": 2,
+    [psym]: 4,
+    1: 1,
+  };
+  var P = new Proxy(O, {
+    ownKeys(target) {
+      log.push("ownKeys()");
+      return Reflect.ownKeys(target);
+    },
+    getOwnPropertyDescriptor(target, name) {
+      log.push(`getOwnPropertyDescriptor(${String(name)})`);
+      return Reflect.getOwnPropertyDescriptor(target, name);
+    },
+    get(target, name) { assertUnreachable(); },
+    set(target, name, value) { assertUnreachable(); },
+    deleteProperty(target, name) { assertUnreachable(); },
+    defineProperty(target, name, desc) { assertUnreachable(); }
+  });
+
+  var result1 = Object.getOwnPropertyDescriptors(O);
+  assertEquals({
+    0: DataDescriptor(0),
+    1: DataDescriptor(1),
+    "a": DataDescriptor(2),
+    [sym]: DataDescriptor(3)
+  }, result1);
+
+  var result2 = Object.getOwnPropertyDescriptors(P);
+  assertEquals([
+    "ownKeys()",
+    "getOwnPropertyDescriptor(0)",
+    "getOwnPropertyDescriptor(1)",
+    "getOwnPropertyDescriptor(a)",
+    "getOwnPropertyDescriptor(Symbol(foo))"
+  ], log);
+  assertEquals({
+    0: DataDescriptor(0),
+    1: DataDescriptor(1),
+    "a": DataDescriptor(2),
+    [sym]: DataDescriptor(3)
+  }, result2);
+}
+TestTypeFilteringAndOrder();
+
+
+function TestDuplicateKeys() {
+  var i = 0;
+  var log = [];
+  var P = new Proxy({}, {
+    ownKeys() {
+      log.push(`ownKeys()`);
+      return ["A", "A"];
+    },
+    getOwnPropertyDescriptor(t, name) {
+      log.push(`getOwnPropertyDescriptor(${name})`);
+      if (i++) return;
+      return {
+        configurable: true,
+        writable: false,
+        value: "VALUE"
+      };
+    },
+    get(target, name) { assertUnreachable(); },
+    set(target, name, value) { assertUnreachable(); },
+    deleteProperty(target, name) { assertUnreachable(); },
+    defineProperty(target, name, desc) { assertUnreachable(); }
+  });
+
+  var result = Object.getOwnPropertyDescriptors(P);
+  assertEquals({ "A": undefined }, result);
+  assertTrue(result.hasOwnProperty("A"));
+  assertEquals([
+    "ownKeys()",
+    "getOwnPropertyDescriptor(A)",
+    "getOwnPropertyDescriptor(A)"
+  ], log);
+}
+TestDuplicateKeys();
diff --git a/test/mjsunit/harmony/object-values.js b/test/mjsunit/harmony/object-values.js
new file mode 100644
index 0000000..f56fe8a
--- /dev/null
+++ b/test/mjsunit/harmony/object-values.js
@@ -0,0 +1,229 @@
+// Copyright 2016 the V8 project 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-values-entries --harmony-proxies --harmony-reflect
+// Flags: --allow-natives-syntax
+
+function TestMeta() {
+  assertEquals(1, Object.values.length);
+  assertEquals(Function.prototype, Object.getPrototypeOf(Object.values));
+  assertEquals("values", Object.values.name);
+
+  var descriptor = Object.getOwnPropertyDescriptor(Object, "values");
+  assertTrue(descriptor.writable);
+  assertFalse(descriptor.enumerable);
+  assertTrue(descriptor.configurable);
+
+  assertThrows(() => new Object.values({}), TypeError);
+}
+TestMeta();
+
+
+function TestBasic() {
+  var x = 16;
+  var O = {
+    d: 1,
+    c: 3,
+    [Symbol.iterator]: void 0,
+    0: 123,
+    1000: 456,
+    [x * x]: "ducks",
+    [`0x${(x * x).toString(16)}`]: "quack"
+  };
+  O.a = 2;
+  O.b = 4;
+  Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
+  assertEquals([123, "ducks", 456, 1, 3, "quack", 2, 4], Object.values(O));
+  assertEquals(Object.values(O), Object.keys(O).map(key => O[key]));
+
+  assertTrue(Array.isArray(Object.values({})));
+  assertEquals(0, Object.values({}).length);
+}
+TestBasic();
+
+
+function TestToObject() {
+  assertThrows(function() { Object.values(); }, TypeError);
+  assertThrows(function() { Object.values(null); }, TypeError);
+  assertThrows(function() { Object.values(void 0); }, TypeError);
+}
+TestToObject();
+
+
+function TestOrder() {
+  var O = {
+    a: 1,
+    [Symbol.iterator]: null
+  };
+  O[456] = 123;
+  Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
+  var priv = %CreatePrivateSymbol("Secret");
+  O[priv] = 56;
+
+  var log = [];
+  var P = new Proxy(O, {
+    ownKeys(target) {
+      log.push("[[OwnPropertyKeys]]");
+      return Reflect.ownKeys(target);
+    },
+    get(target, name) {
+      log.push(`[[Get]](${JSON.stringify(name)})`);
+      return Reflect.get(target, name);
+    },
+    getOwnPropertyDescriptor(target, name) {
+      log.push(`[[GetOwnProperty]](${JSON.stringify(name)})`);
+      return Reflect.getOwnPropertyDescriptor(target, name);
+    },
+    set(target, name, value) {
+      assertUnreachable();
+    }
+  });
+
+  assertEquals([123, 1], Object.values(P));
+  assertEquals([
+    "[[OwnPropertyKeys]]",
+    "[[GetOwnProperty]](\"456\")",
+    "[[Get]](\"456\")",
+    "[[GetOwnProperty]](\"a\")",
+    "[[Get]](\"a\")",
+    "[[GetOwnProperty]](\"HIDDEN\")"
+  ], log);
+}
+TestOrder();
+
+
+function TestOrderWithDuplicates() {
+  var O = {
+    a: 1,
+    [Symbol.iterator]: null
+  };
+  O[456] = 123;
+  Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
+  O[priv] = 56;
+  var priv = %CreatePrivateSymbol("private");
+
+  var log = [];
+  var P = new Proxy(O, {
+    ownKeys(target) {
+      log.push("[[OwnPropertyKeys]]");
+      return [ "a", Symbol.iterator, "a", "456", "HIDDEN", "HIDDEN", "456" ];
+    },
+    get(target, name) {
+      log.push(`[[Get]](${JSON.stringify(name)})`);
+      return Reflect.get(target, name);
+    },
+    getOwnPropertyDescriptor(target, name) {
+      log.push(`[[GetOwnProperty]](${JSON.stringify(name)})`);
+      return Reflect.getOwnPropertyDescriptor(target, name);
+    },
+    set(target, name, value) {
+      assertUnreachable();
+    }
+  });
+
+  assertEquals([1, 1, 123, 123], Object.values(P));
+  assertEquals([
+    "[[OwnPropertyKeys]]",
+    "[[GetOwnProperty]](\"a\")",
+    "[[Get]](\"a\")",
+    "[[GetOwnProperty]](\"a\")",
+    "[[Get]](\"a\")",
+    "[[GetOwnProperty]](\"456\")",
+    "[[Get]](\"456\")",
+    "[[GetOwnProperty]](\"HIDDEN\")",
+    "[[GetOwnProperty]](\"HIDDEN\")",
+    "[[GetOwnProperty]](\"456\")",
+    "[[Get]](\"456\")",
+  ], log);
+}
+TestOrderWithDuplicates();
+
+
+function TestPropertyFilter() {
+  var object = { prop3: 30 };
+  object[2] = 40;
+  object["prop4"] = 50;
+  Object.defineProperty(object, "prop5", { value: 60, enumerable: true });
+  Object.defineProperty(object, "prop6", { value: 70, enumerable: false });
+  Object.defineProperty(object, "prop7", {
+      enumerable: true, get() { return 80; }});
+  var sym = Symbol("prop8");
+  object[sym] = 90;
+
+  values = Object.values(object);
+  assertEquals(5, values.length);
+  assertEquals([40,30,50,60,80], values);
+}
+TestPropertyFilter();
+
+
+function TestWithProxy() {
+  var obj1 = {prop1:10};
+  var proxy1 = new Proxy(obj1, { });
+  assertEquals([10], Object.values(proxy1));
+
+  var obj2 = {};
+  Object.defineProperty(obj2, "prop2", { value: 20, enumerable: true });
+  Object.defineProperty(obj2, "prop3", {
+      get() { return 30; }, enumerable: true });
+  var proxy2 = new Proxy(obj2, {
+    getOwnPropertyDescriptor(target, name) {
+      return Reflect.getOwnPropertyDescriptor(target, name);
+    }
+  });
+  assertEquals([20, 30], Object.values(proxy2));
+
+  var obj3 = {};
+  var count = 0;
+  var proxy3 = new Proxy(obj3, {
+    get(target, property, receiver) {
+      return count++ * 5;
+    },
+    getOwnPropertyDescriptor(target, property) {
+      return { configurable: true, enumerable: true };
+    },
+    ownKeys(target) {
+      return [ "prop0", "prop1", Symbol("prop2"), Symbol("prop5") ];
+    }
+  });
+  assertEquals([0, 5], Object.values(proxy3));
+}
+TestWithProxy();
+
+
+function TestMutateDuringEnumeration() {
+  var aDeletesB = {
+    get a() {
+      delete this.b;
+      return 1;
+    },
+    b: 2
+  };
+  assertEquals([1], Object.values(aDeletesB));
+
+  var aRemovesB = {
+    get a() {
+      Object.defineProperty(this, "b", { enumerable: false });
+      return 1;
+    },
+    b: 2
+  };
+  assertEquals([1], Object.values(aRemovesB));
+
+  var aAddsB = { get a() { this.b = 2; return 1; } };
+  assertEquals([1], Object.values(aAddsB));
+
+  var aMakesBEnumerable = {};
+  Object.defineProperty(aMakesBEnumerable, "a", {
+    get() {
+      Object.defineProperty(this, "b", { enumerable: true });
+      return 1;
+    },
+    enumerable: true
+  });
+  Object.defineProperty(aMakesBEnumerable, "b", {
+      value: 2, configurable:true, enumerable: false });
+  assertEquals([1, 2], Object.values(aMakesBEnumerable));
+}
+TestMutateDuringEnumeration();
diff --git a/test/mjsunit/harmony/private-symbols.js b/test/mjsunit/harmony/private-symbols.js
index 369c222..18a2e4c 100644
--- a/test/mjsunit/harmony/private-symbols.js
+++ b/test/mjsunit/harmony/private-symbols.js
@@ -16,7 +16,6 @@
 for (var key of Object.getOwnPropertySymbols(object)) assertUnreachable();
 for (var key of Object.getOwnPropertyNames(object)) assertUnreachable();
 for (var key of Reflect.ownKeys(object)) assertUnreachable();
-for (var key of Reflect.enumerate(object)) assertUnreachable();
 for (var key in object) assertUnreachable();
 
 var object2 = {__proto__: object};
@@ -24,7 +23,6 @@
 for (var key of Object.getOwnPropertySymbols(object2)) assertUnreachable();
 for (var key of Object.getOwnPropertyNames(object2)) assertUnreachable();
 for (var key of Reflect.ownKeys(object2)) assertUnreachable();
-for (var key of Reflect.enumerate(object2)) assertUnreachable();
 for (var key in object2) assertUnreachable();
 
 
diff --git a/test/mjsunit/harmony/proxies-apply.js b/test/mjsunit/harmony/proxies-apply.js
index 4ddffe7..dae362a 100644
--- a/test/mjsunit/harmony/proxies-apply.js
+++ b/test/mjsunit/harmony/proxies-apply.js
@@ -87,3 +87,36 @@
   assertTrue(called_target);
   assertTrue(called_handler);
 })();
+
+
+(function testCallProxyNonCallableTarget() {
+  var values = [NaN, 1.5, 100, /RegExp/, "string", {}, [], Symbol(),
+                new Map(), new Set(), new WeakMap(), new WeakSet()];
+  values.forEach(target => {
+    target = Object(target);
+    var proxy = new Proxy(target, { apply() { assertUnreachable(); } });
+    assertThrows(() => { proxy(); }, TypeError);
+    assertThrows(() => { ({ proxy }).proxy(); }, TypeError);
+    assertThrows(() => { Reflect.apply(proxy, null, []); }, TypeError);
+    assertThrows(() => { Reflect.apply(proxy, { proxy }, []); }, TypeError);
+    assertThrows(() => {
+          Function.prototype.call.apply(proxy, [null]);
+        }, TypeError);
+    assertThrows(() => {
+          Function.prototype.apply.apply(proxy, [null, []]);
+        }, TypeError);
+
+    var proxy_to_proxy = new Proxy(proxy, { apply() { assertUnreachable(); } });
+    assertThrows(() => { proxy_to_proxy(); }, TypeError);
+    assertThrows(() => { ({ proxy_to_proxy }).proxy_to_proxy(); }, TypeError);
+    assertThrows(() => { Reflect.apply(proxy_to_proxy, null, []); }, TypeError);
+    assertThrows(() => { Reflect.apply(proxy_to_proxy, { proxy }, []); },
+                 TypeError);
+    assertThrows(() => {
+          Function.prototype.call.apply(proxy_to_proxy, [null]);
+        }, TypeError);
+    assertThrows(() => {
+          Function.prototype.apply.apply(proxy_to_proxy, [null, []]);
+        }, TypeError);
+  });
+})();
diff --git a/test/mjsunit/harmony/proxies-enumerate.js b/test/mjsunit/harmony/proxies-enumerate.js
deleted file mode 100644
index 82464d0..0000000
--- a/test/mjsunit/harmony/proxies-enumerate.js
+++ /dev/null
@@ -1,109 +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-proxies
-
-var target = {
-  "target_one": 1
-};
-target.__proto__ = {
-  "target_two": 2
-};
-var handler = {
-  enumerate: function(target) {
-    function* keys() {
-      yield "foo";
-      yield "bar";
-    }
-    return keys();
-  },
-  // For-in calls "has" on every iteration, so for TestForIn() below to
-  // detect all results of the "enumerate" trap, "has" must return true.
-  has: function(target, name) {
-    return true;
-  }
-}
-
-var proxy = new Proxy(target, handler);
-
-function TestForIn(receiver, expected) {
-  var result = [];
-  for (var k in receiver) {
-    result.push(k);
-  }
-  assertEquals(expected, result);
-}
-
-TestForIn(proxy, ["foo", "bar"]);
-
-// Test revoked proxy.
-var pair = Proxy.revocable(target, handler);
-TestForIn(pair.proxy, ["foo", "bar"]);
-pair.revoke();
-assertThrows(()=>{ TestForIn(pair.proxy, ["foo", "bar"]) }, TypeError);
-
-// Properly call traps on proxies on the prototype chain.
-var receiver = {
-  "receiver_one": 1
-};
-receiver.__proto__ = proxy;
-TestForIn(receiver, ["receiver_one", "foo", "bar"]);
-
-// Fall through to default behavior when trap is undefined.
-handler.enumerate = undefined;
-TestForIn(proxy, ["target_one", "target_two"]);
-delete handler.enumerate;
-TestForIn(proxy, ["target_one", "target_two"]);
-
-// Non-string keys must be filtered.
-function TestNonStringKey(key) {
-  handler.enumerate = function(target) {
-    function* keys() { yield key; }
-    return keys();
-  }
-  assertThrows("for (var k in proxy) {}", TypeError);
-}
-
-TestNonStringKey(1);
-TestNonStringKey(3.14);
-TestNonStringKey(Symbol("foo"));
-TestNonStringKey({bad: "value"});
-TestNonStringKey(null);
-TestNonStringKey(undefined);
-TestNonStringKey(true);
-
-(function testProtoProxyEnumerate() {
-  var keys = ['a', 'b', 'c', 'd'];
-  var handler = {
-   enumerate() { return keys[Symbol.iterator]() },
-   has(target, key) { return false }
-  };
-  var proxy = new Proxy({}, handler);
-  var seen_keys = [];
-  for (var i in proxy) {
-    seen_keys.push(i);
-  }
-  assertEquals([], seen_keys);
-
-  handler.has = function(target, key) { return true };
-  for (var i in proxy) {
-    seen_keys.push(i);
-  }
-  assertEquals(keys, seen_keys);
-
-  o = {__proto__:proxy};
-  handler.has = function(target, key) { return false };
-  seen_keys = [];
-  for (var i in o) {
-    seen_keys.push(i);
-  }
-  assertEquals([], seen_keys);
-
-  handler.has = function(target, key) { return true };
-  seen_keys = [];
-  for (var i in o) {
-    seen_keys.push(i);
-  }
-  assertEquals(keys, seen_keys);
-})();
diff --git a/test/mjsunit/harmony/proxies-for.js b/test/mjsunit/harmony/proxies-for.js
index aea9bd6..e52ee43 100644
--- a/test/mjsunit/harmony/proxies-for.js
+++ b/test/mjsunit/harmony/proxies-for.js
@@ -27,21 +27,15 @@
 
 // Flags: --harmony-proxies
 
-
 // Helper.
 
 function TestWithProxies(test, x, y, z) {
   test(function(h){ return new Proxy({}, h) }, x, y, z)
-  test(function(h) {
-    return new Proxy(function() {}, h)
-  }, x, y, z)
 }
 
 
 // Iterate over a proxy.
 
-Array.prototype.values = function() { return this[Symbol.iterator]() }
-
 function TestForIn(properties, handler) {
   TestWithProxies(TestForIn2, properties, handler)
 }
@@ -54,23 +48,18 @@
 }
 
 TestForIn(["0", "a"], {
-  enumerate() { return ["0", "a"].values() },
-  has(target, property) { return true }
+  ownKeys() { return ["0", "a"] },
+  has(target, property) { return true },
+  getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }}
 })
 
 TestForIn(["null", "a"], {
-  enumerate() { return this.enumerate2() },
-  enumerate2() { return ["null", "a"].values() },
-  has(target, property) { return true }
+  ownKeys() { return this.enumerate() },
+  enumerate() { return ["null", "a"] },
+  has(target, property) { return true },
+  getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }}
 })
 
-TestForIn(["b", "a", "0", "c"], new Proxy({}, {
-  get: function(pr, pk) {
-    return function() { return ["b", "a", "0", "c"].values() }
-  }
-}))
-
-
 
 // Iterate over an object with a proxy prototype.
 
@@ -94,19 +83,21 @@
 }
 
 TestForInDerived(["0", "a"], {
-  enumerate: function() { return ["0", "a"].values() },
-  has: function(t, k) { return k == "0" || k == "a" }
+  ownKeys: function() { return ["0", "a"] },
+  has: function(t, k) { return k == "0" || k == "a" },
+  getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }}
 })
 
 TestForInDerived(["null", "a"], {
-  enumerate: function() { return this.enumerate2() },
-  enumerate2: function() { return ["null", "a"].values() },
-  has: function(t, k) { return k == "null" || k == "a" }
+  ownKeys: function() { return this.enumerate() },
+  enumerate: function() { return ["null", "a"] },
+  has: function(t, k) { return k == "null" || k == "a" },
+  getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }}
 })
 
 
 
-// Throw exception in enumerate trap.
+// Throw exception in ownKeys trap.
 
 function TestForInThrow(handler) {
   TestWithProxies(TestForInThrow2, handler)
@@ -120,12 +111,12 @@
 }
 
 TestForInThrow({
-  enumerate: function() { throw "myexn" }
+  ownKeys: function() { throw "myexn" }
 })
 
 TestForInThrow({
-  enumerate: function() { return this.enumerate2() },
-  enumerate2: function() { throw "myexn" }
+  ownKeys: function() { return this.enumerate() },
+  enumerate: function() { throw "myexn" }
 })
 
 TestForInThrow(new Proxy({}, {
@@ -135,7 +126,7 @@
 }));
 
 (function() {
-  var p = new Proxy({}, {enumerate:function() { return ["0"].values(); }});
+  var p = new Proxy({}, {ownKeys:function() { return ["0"]; }});
   var o = [0];
   o.__proto__ = p;
   var keys = [];
diff --git a/test/mjsunit/harmony/proxies-ownkeys.js b/test/mjsunit/harmony/proxies-ownkeys.js
index 6a7ae64..88350cc 100644
--- a/test/mjsunit/harmony/proxies-ownkeys.js
+++ b/test/mjsunit/harmony/proxies-ownkeys.js
@@ -56,6 +56,10 @@
 keys.length = Math.pow(2, 33);
 assertThrows("Reflect.ownKeys(proxy)", RangeError);
 
+// Check that we allow duplicated keys.
+keys  = ['a', 'a', 'a']
+assertEquals(keys, Reflect.ownKeys(proxy));
+
 // Non-Name results throw.
 keys = [1];
 assertThrows("Reflect.ownKeys(proxy)", TypeError);
@@ -73,6 +77,10 @@
 keys = ["nonconf"];
 assertEquals(keys, Reflect.ownKeys(proxy));
 
+// Check that we allow duplicated keys.
+keys  = ['nonconf', 'nonconf', 'nonconf']
+assertEquals(keys, Reflect.ownKeys(proxy));
+
 // Step 19a: The trap result must all keys of a non-extensible target.
 Object.preventExtensions(target);
 assertThrows("Reflect.ownKeys(proxy)", TypeError);
@@ -82,3 +90,7 @@
 // Step 20: The trap result must not add keys to a non-extensible target.
 keys = ["nonconf", "target_one", "fantasy"];
 assertThrows("Reflect.ownKeys(proxy)", TypeError);
+
+// Check that we allow duplicated keys.
+keys  = ['nonconf', 'target_one', 'nonconf', 'nonconf', 'target_one',]
+assertEquals(keys, Reflect.ownKeys(proxy));
diff --git a/test/mjsunit/harmony/proxies-set-prototype-of.js b/test/mjsunit/harmony/proxies-set-prototype-of.js
index bc60ff4..810c219 100644
--- a/test/mjsunit/harmony/proxies-set-prototype-of.js
+++ b/test/mjsunit/harmony/proxies-set-prototype-of.js
@@ -120,3 +120,11 @@
   prototype = [5];
   assertThrows(() => {Reflect.setPrototypeOf(proxy2, prototype)}, TypeError);
 })();
+
+(function testProxyTrapReturnsFalse() {
+  var handler = {};
+  handler.setPrototypeOf = () => false;
+  var target = new Proxy({}, {isExtensible: () => assertUnreachable()});
+  var object = new Proxy(target, handler);
+  assertFalse(Reflect.setPrototypeOf(object, {}));
+})();
diff --git a/test/mjsunit/harmony/reflect-construct.js b/test/mjsunit/harmony/reflect-construct.js
index f2dfc15..c136957 100644
--- a/test/mjsunit/harmony/reflect-construct.js
+++ b/test/mjsunit/harmony/reflect-construct.js
@@ -279,10 +279,7 @@
 (function() {
   function* f() { yield 1; yield 2; }
   function* g() { yield 3; yield 4; }
-  var o = Reflect.construct(f, [], g);
-  assertEquals([1, 2], [...o]);
-  assertTrue(o.__proto__ === g.prototype);
-  assertTrue(o.__proto__ !== f.prototype);
+  assertThrows(()=>Reflect.construct(f, [], g));
 })();
 
 (function () {
diff --git a/test/mjsunit/harmony/reflect-enumerate-delete.js b/test/mjsunit/harmony/reflect-enumerate-delete.js
deleted file mode 100644
index 1137d8a..0000000
--- a/test/mjsunit/harmony/reflect-enumerate-delete.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2010-2015 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 properties deleted during an enumeration do not show up in
-// the enumeration.  This is adapted from mjsunit/for-in-delete.js.
-
-// Flags: --harmony-reflect
-
-
-function f(o, expected, del) {
-  var index = 0;
-  for (p of Reflect.enumerate(o)) {
-    if (del) delete o[del];
-    assertEquals(expected[index], p);
-    index++;
-  }
-  assertEquals(expected.length, index);
-}
-
-var o = {}
-o.a = 1;
-o.b = 2;
-o.c = 3;
-o.d = 3;
-
-f(o, ['a', 'b', 'c', 'd']);
-f(o, ['a', 'b', 'c', 'd']);
-f(o, ['a', 'c', 'd'], 'b');
-f(o, ['a', 'c'], 'd');
diff --git a/test/mjsunit/harmony/reflect-enumerate-opt.js b/test/mjsunit/harmony/reflect-enumerate-opt.js
deleted file mode 100644
index ccd1845..0000000
--- a/test/mjsunit/harmony/reflect-enumerate-opt.js
+++ /dev/null
@@ -1,78 +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.
-
-// This is adapted from mjsunit/for-in-opt.js.
-
-// Flags: --harmony-proxies --harmony-reflect --allow-natives-syntax
-
-
-"use strict";
-
-function f(o) {
-  var result = [];
-  for (var i of Reflect.enumerate(Object(o))) {
-    result.push(i);
-  }
-  return result;
-}
-
-assertEquals(["0"], f("a"));
-assertEquals(["0"], f("a"));
-%OptimizeFunctionOnNextCall(f);
-assertEquals(["0","1","2"], f("bla"));
-
-// Test the lazy deopt points.
-var keys = ["a", "b", "c", "d"];
-var has_keys = [];
-var deopt_has = false;
-var deopt_enum = false;
-
-var handler = {
-  enumerate: function(target) {
-    if (deopt_enum) {
-      %DeoptimizeFunction(f2);
-      deopt_enum = false;
-    }
-    return keys;
-  },
-
-  getPropertyDescriptor: function(k) {
-    if (deopt_has) {
-      %DeoptimizeFunction(f2);
-      deopt_has = false;
-    }
-    has_keys.push(k);
-    return {value: 10, configurable: true, writable: false, enumerable: true};
-  }
-};
-
-// TODO(neis,cbruni): Enable once the enumerate proxy trap is properly
-// implemented.
-// var proxy = new Proxy({}, handler);
-// var o = {__proto__: proxy};
-//
-// function f2(o) {
-//   var result = [];
-//   for (var i of Reflect.enumerate(o)) {
-//     result.push(i);
-//   }
-//   return result;
-// }
-//
-// function check_f2() {
-//   assertEquals(keys, f2(o));
-//   assertEquals(keys, has_keys);
-//   has_keys.length = 0;
-// }
-//
-// check_f2();
-// check_f2();
-// Test lazy deopt after GetPropertyNamesFast
-// %OptimizeFunctionOnNextCall(f2);
-// deopt_enum = true;
-// check_f2();
-// Test lazy deopt after FILTER_KEY
-// %OptimizeFunctionOnNextCall(f2);
-// deopt_has = true;
-// check_f2();
diff --git a/test/mjsunit/harmony/reflect-enumerate-special-cases.js b/test/mjsunit/harmony/reflect-enumerate-special-cases.js
deleted file mode 100644
index 234a3e3..0000000
--- a/test/mjsunit/harmony/reflect-enumerate-special-cases.js
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2008-2015 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 is adapted from mjsunit/for-in-special-cases.js.
-
-// Flags: --harmony-reflect
-
-
-function Accumulate(x) {
-  var accumulator = "";
-  for (var i of Reflect.enumerate(Object(x))) {
-    accumulator += i;
-  }
-  return accumulator;
-}
-
-for (var i = 0; i < 3; ++i) {
-  var elements = Accumulate("abcd");
-  // We do not assume that enumerate enumerates elements in order.
-  assertTrue(-1 != elements.indexOf("0"));
-  assertTrue(-1 != elements.indexOf("1"));
-  assertTrue(-1 != elements.indexOf("2"));
-  assertTrue(-1 != elements.indexOf("3"));
-  assertEquals(4, elements.length);
-}
-
-function for_in_string_prototype() {
-
-  var x = new String("abc");
-  x.foo = 19;
-  function B() {
-    this.bar = 5;
-    this[7] = 4;
-  }
-  B.prototype = x;
-
-  var y = new B();
-  y.gub = 13;
-
-  var elements = Accumulate(y);
-  var elements1 = Accumulate(y);
-  // If enumerate returns elements in a different order on multiple calls, this
-  // assert will fail.  If that happens, consider if that behavior is OK.
-  assertEquals(elements, elements1, "Enumeration not the same both times.");
-  // We do not assume that enumerate enumerates elements in order.
-  assertTrue(-1 != elements.indexOf("0"));
-  assertTrue(-1 != elements.indexOf("1"));
-  assertTrue(-1 != elements.indexOf("2"));
-  assertTrue(-1 != elements.indexOf("7"));
-  assertTrue(-1 != elements.indexOf("foo"));
-  assertTrue(-1 != elements.indexOf("bar"));
-  assertTrue(-1 != elements.indexOf("gub"));
-  assertEquals(13, elements.length);
-
-  elements = Accumulate(x);
-  assertTrue(-1 != elements.indexOf("0"));
-  assertTrue(-1 != elements.indexOf("1"));
-  assertTrue(-1 != elements.indexOf("2"));
-  assertTrue(-1 != elements.indexOf("foo"));
-  assertEquals(6, elements.length);
-}
-
-for_in_string_prototype();
-for_in_string_prototype();
diff --git a/test/mjsunit/harmony/reflect-enumerate.js b/test/mjsunit/harmony/reflect-enumerate.js
deleted file mode 100644
index bbc364e..0000000
--- a/test/mjsunit/harmony/reflect-enumerate.js
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2008-2015 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 is adapted from mjsunit/for-in.js.
-
-// Flags: --harmony-reflect
-
-
-function props(x) {
-  var array = [];
-  for (var p of Reflect.enumerate(x)) array.push(p);
-  return array.sort();
-}
-
-assertEquals(0, props({}).length, "olen0");
-assertEquals(1, props({x:1}).length, "olen1");
-assertEquals(2, props({x:1, y:2}).length, "olen2");
-
-assertArrayEquals(["x"], props({x:1}), "x");
-assertArrayEquals(["x", "y"], props({x:1, y:2}), "xy");
-assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3}), "xyzoom");
-
-assertEquals(0, props([]).length, "alen0");
-assertEquals(1, props([1]).length, "alen1");
-assertEquals(2, props([1,2]).length, "alen2");
-
-assertArrayEquals(["0"], props([1]), "0");
-assertArrayEquals(["0", "1"], props([1,2]), "01");
-assertArrayEquals(["0", "1", "2"], props([1,2,3]), "012");
-
-var o = {};
-var a = [];
-for (var i = 0x0020; i < 0x01ff; i+=2) {
-  var s = 'char:' + String.fromCharCode(i);
-  a.push(s);
-  o[s] = i;
-}
-assertArrayEquals(a, props(o), "charcodes");
-
-var a = [];
-assertEquals(0, props(a).length, "proplen0");
-a[Math.pow(2,30)-1] = 0;
-assertEquals(1, props(a).length, "proplen1");
-a[Math.pow(2,31)-1] = 0;
-assertEquals(2, props(a).length, "proplen2");
-a[1] = 0;
-assertEquals(3, props(a).length, "proplen3");
-
-var result = '';
-for (var p of Reflect.enumerate({a : [0], b : 1})) { result += p; }
-assertEquals('ab', result, "ab");
-
-var result = '';
-for (var p of Reflect.enumerate({a : {v:1}, b : 1})) { result += p; }
-assertEquals('ab', result, "ab-nodeep");
-
-var result = '';
-for (var p of Reflect.enumerate({ get a() {}, b : 1})) { result += p; }
-assertEquals('ab', result, "abget");
-
-var result = '';
-for (var p of Reflect.enumerate({ get a() {}, set a(x) {}, b : 1})) {
-  result += p;
-}
-assertEquals('ab', result, "abgetset");
-
-(function() {
-  var large_key = 2147483650;
-  var o = {__proto__: {}};
-  o[large_key] = 1;
-  o.__proto__[large_key] = 1;
-  var keys = [];
-  for (var k of Reflect.enumerate(o)) {
-    keys.push(k);
-  }
-  assertEquals(["2147483650"], keys);
-})();
diff --git a/test/mjsunit/harmony/reflect.js b/test/mjsunit/harmony/reflect.js
index 8ee1227..6449eb8 100644
--- a/test/mjsunit/harmony/reflect.js
+++ b/test/mjsunit/harmony/reflect.js
@@ -486,27 +486,6 @@
 })();
 
 
-
-////////////////////////////////////////////////////////////////////////////////
-// Reflect.enumerate
-
-
-(function testReflectEnumerateArity() {
-  assertEquals(1, Reflect.enumerate.length);
-})();
-
-
-(function testReflectEnumerateOnNonObject() {
-  assertThrows(function() { Reflect.enumerate(); }, TypeError);
-  assertThrows(function() { Reflect.enumerate(42); }, TypeError);
-  assertThrows(function() { Reflect.enumerate(null); }, TypeError);
-})();
-
-
-// See reflect-enumerate*.js for further tests.
-
-
-
 ////////////////////////////////////////////////////////////////////////////////
 // Reflect.getOwnPropertyDescriptor
 
diff --git a/test/mjsunit/harmony/regress/regress-4696.js b/test/mjsunit/harmony/regress/regress-4696.js
new file mode 100644
index 0000000..82969f9
--- /dev/null
+++ b/test/mjsunit/harmony/regress/regress-4696.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 testSpreadIndex() {
+  var result = [...[17, 42]][1];
+  assertEquals(result, 42);
+})();
+
+(function testSpreadProperty() {
+  var result = [...[17, 42]].length;
+  assertEquals(result, 2);
+})();
+
+(function testSpreadMethodCall() {
+  var result = [...[17, 42]].join("+");
+  assertEquals(result, "17+42");
+})();
+
+(function testSpreadSavedMethodCall() {
+  var x = [...[17, 42]];
+  var method = x.join;
+  var result = method.call(x, "+");
+  assertEquals(result, "17+42");
+})();
+
+(function testSpreadAsTemplateTag() {
+  assertThrows(function() { [...[17, 42]] `foo`; }, TypeError)
+})();
diff --git a/test/mjsunit/harmony/regress/regress-4755.js b/test/mjsunit/harmony/regress/regress-4755.js
new file mode 100644
index 0000000..2a0df9d
--- /dev/null
+++ b/test/mjsunit/harmony/regress/regress-4755.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 --harmony-do-expressions
+
+(function DoTryCatchInsideBinop() {
+  function f(a, b) {
+    return a + do { try { throw "boom" } catch(e) { b } }
+  }
+  assertEquals(3, f(1, 2));
+  assertEquals(3, f(1, 2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(3, f(1, 2));
+})();
+
+(function DoTryCatchInsideCall() {
+  function f(a, b) {
+    return Math.max(a, do { try { throw a } catch(e) { e + b } })
+  }
+  assertEquals(3, f(1, 2));
+  assertEquals(3, f(1, 2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(3, f(1, 2));
+})();
+
+(function DoTryCatchInsideTry() {
+  function f(a, b) {
+    try { return do { try { throw a } catch(e) { e + b } } } catch(e) {}
+  }
+  assertEquals(3, f(1, 2));
+  assertEquals(3, f(1, 2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(3, f(1, 2));
+})();
+
+(function DoTryCatchInsideFinally() {
+  function f(a, b) {
+    try {} finally { return do { try { throw a } catch(e) { e + b } } }
+  }
+  assertEquals(3, f(1, 2));
+  assertEquals(3, f(1, 2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(3, f(1, 2));
+})();
diff --git a/test/mjsunit/harmony/regress/regress-crbug-578038.js b/test/mjsunit/harmony/regress/regress-crbug-578038.js
new file mode 100644
index 0000000..42774b8
--- /dev/null
+++ b/test/mjsunit/harmony/regress/regress-crbug-578038.js
@@ -0,0 +1,16 @@
+// 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 testWithoutOtherLiteral() {
+  var result = ((x = [...[42]]) => x)();
+  assertEquals(result, [42]);
+})();
+
+(function testWithSomeOtherLiteral() {
+  []; // important: an array literal before the arrow function
+  var result = ((x = [...[42]]) => x)();  // will core dump, if not fixed.
+  assertEquals(result, [42]);
+})();
diff --git a/test/mjsunit/harmony/simd.js b/test/mjsunit/harmony/simd.js
index 6330ac8..ff81506 100644
--- a/test/mjsunit/harmony/simd.js
+++ b/test/mjsunit/harmony/simd.js
@@ -407,7 +407,7 @@
   var simdFn = SIMD[type];
   var instance = createInstance(type);
   var sameValue = Object.is
-  var sameValueZero = natives.ImportNow("SameValueZero");
+  var sameValueZero = function(x, y) { return %SameValueZero(x, y); }
 
   // SIMD values should not be the same as instances of different types.
   checkTypeMatrix(type, function(other) {
diff --git a/test/mjsunit/harmony/string-replace.js b/test/mjsunit/harmony/string-replace.js
new file mode 100644
index 0000000..208c483
--- /dev/null
+++ b/test/mjsunit/harmony/string-replace.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.
+
+// 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/unicode-character-ranges.js b/test/mjsunit/harmony/unicode-character-ranges.js
new file mode 100644
index 0000000..e4f5247
--- /dev/null
+++ b/test/mjsunit/harmony/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-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
index f591dac..895e0c6 100644
--- a/test/mjsunit/harmony/unicode-escapes-in-regexps.js
+++ b/test/mjsunit/harmony/unicode-escapes-in-regexps.js
@@ -252,6 +252,36 @@
 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"));
-assertTrue(/\ud808\udf45{3}/u.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
new file mode 100644
index 0000000..e02301b
--- /dev/null
+++ b/test/mjsunit/harmony/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-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
new file mode 100644
index 0000000..a4cb9dc
--- /dev/null
+++ b/test/mjsunit/harmony/unicode-regexp-ignore-case-noi18n.js
@@ -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.
+
+// 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
new file mode 100644
index 0000000..291b866
--- /dev/null
+++ b/test/mjsunit/harmony/unicode-regexp-ignore-case.js
@@ -0,0 +1,64 @@
+// Copyright 2016 the V8 project 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
new file mode 100644
index 0000000..4a075d4
--- /dev/null
+++ b/test/mjsunit/harmony/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-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-property-class.js b/test/mjsunit/harmony/unicode-regexp-property-class.js
new file mode 100644
index 0000000..323873a
--- /dev/null
+++ b/test/mjsunit/harmony/unicode-regexp-property-class.js
@@ -0,0 +1,64 @@
+// Copyright 2016 the V8 project 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 --harmony-unicode-regexps
+
+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{Ll}/u.test("a"));
+assertFalse(/\P{Ll}/u.test("a"));
+assertTrue(/\P{Ll}/u.test("A"));
+assertFalse(/\p{Ll}/u.test("A"));
+assertTrue(/\p{Ll}/u.test("\u{1D7BE}"));
+assertFalse(/\P{Ll}/u.test("\u{1D7BE}"));
+assertFalse(/\p{Ll}/u.test("\u{1D5E3}"));
+assertTrue(/\P{Ll}/u.test("\u{1D5E3}"));
+
+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}"));
+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{Lu}/u.test("A"));
+assertFalse(/\P{Lu}/u.test("A"));
+assertTrue(/\P{Lu}/u.test("a"));
+assertFalse(/\p{Lu}/u.test("a"));
+assertTrue(/\p{Lu}/u.test("\u{1D5E3}"));
+assertFalse(/\P{Lu}/u.test("\u{1D5E3}"));
+assertFalse(/\p{Lu}/u.test("\u{1D7BE}"));
+assertTrue(/\P{Lu}/u.test("\u{1D7BE}"));
+
+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}"));
+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{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/unicode-regexp-restricted-syntax.js b/test/mjsunit/harmony/unicode-regexp-restricted-syntax.js
new file mode 100644
index 0000000..d129cc3
--- /dev/null
+++ b/test/mjsunit/harmony/unicode-regexp-restricted-syntax.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: --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
new file mode 100644
index 0000000..97960e1
--- /dev/null
+++ b/test/mjsunit/harmony/unicode-regexp-unanchored-advance.js
@@ -0,0 +1,8 @@
+// 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
new file mode 100644
index 0000000..bbc17dc
--- /dev/null
+++ b/test/mjsunit/harmony/unicode-regexp-zero-length.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-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/ignition/dead-code-source-position.js b/test/mjsunit/ignition/dead-code-source-position.js
new file mode 100644
index 0000000..95bb918
--- /dev/null
+++ b/test/mjsunit/ignition/dead-code-source-position.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.
+
+function f() {
+  for (f(x) in []) { f(new f()) }
+}
+
+f();
diff --git a/test/mjsunit/ignition/debug-break-on-stack.js b/test/mjsunit/ignition/debug-break-on-stack.js
new file mode 100644
index 0000000..d2577b3
--- /dev/null
+++ b/test/mjsunit/ignition/debug-break-on-stack.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: --expose-debug-as debug
+
+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();
+  throw 1;  // B1
+}
+
+function f() {
+  try {
+    g();
+  } catch (e) {}
+  return 2;  // B2
+}
+
+function setbreaks() {
+  Debug.setListener(listener);
+  Debug.setBreakPoint(g, 2, 0);
+  Debug.setBreakPoint(f, 4, 0);
+}
+
+f();
+
+assertEquals(2, break_count);
+assertNull(exception);
+
+Debug.setListener(null);
diff --git a/test/mjsunit/ignition/debug-break.js b/test/mjsunit/ignition/debug-break.js
new file mode 100644
index 0000000..8237d4a
--- /dev/null
+++ b/test/mjsunit/ignition/debug-break.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
+
+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() {
+  throw 1;
+}
+
+function f() {
+  try {
+    g();                         // B1
+  } catch (e) {}
+  assertEquals(2, break_count);  // B2
+  return 1;                      // B3
+}
+
+Debug.setBreakPoint(f, 2, 0);
+Debug.setBreakPoint(f, 4, 1);
+Debug.setBreakPoint(f, 5, 1);
+
+f();
+
+assertEquals(3, break_count);
+assertNull(exception);
+
+Debug.setListener(null);
diff --git a/test/mjsunit/ignition/debugger-statement.js b/test/mjsunit/ignition/debugger-statement.js
new file mode 100644
index 0000000..9c2204e
--- /dev/null
+++ b/test/mjsunit/ignition/debugger-statement.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: --ignition-filter=f --expose-debug-as debug
+
+var Debug = debug.Debug;
+
+var break_count = 0;
+
+function f() {
+  debugger;
+}
+
+function listener(event, exec_data) {
+  if (event != Debug.DebugEvent.Break) return;
+  break_count++;
+}
+
+f();
+assertEquals(0, break_count);
+
+Debug.setListener(listener);
+
+f();
+assertEquals(1, break_count);
+
+Debug.setListener(null);
+
+f();
+assertEquals(1, break_count);
diff --git a/test/mjsunit/ignition/stack-trace-source-position.js b/test/mjsunit/ignition/stack-trace-source-position.js
new file mode 100644
index 0000000..ce236c3
--- /dev/null
+++ b/test/mjsunit/ignition/stack-trace-source-position.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: --ignition-filter=f
+// Flags: --no-turbo
+
+// TODO(yangguo): fix for turbofan
+
+function f(x) {
+  if (x == 0) {
+    return new Error().stack;
+  }
+  return f(x - 1);
+}
+
+var stack_lines = f(2).split("\n");
+
+assertTrue(/at f \(.*?:12:12\)/.test(stack_lines[1]));
+assertTrue(/at f \(.*?:14:10\)/.test(stack_lines[2]));
+assertTrue(/at f \(.*?:14:10\)/.test(stack_lines[3]));
diff --git a/test/mjsunit/messages.js b/test/mjsunit/messages.js
index 8da7e6b..7deef02 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 --harmony-reflect --harmony-regexps
-// Flags: --harmony-simd --strong-mode
+// Flags: --harmony-simd
 
 function test(f, expected, type) {
   try {
@@ -150,7 +150,7 @@
 // kInstanceofFunctionExpected
 test(function() {
   1 instanceof 1;
-}, "Expecting a function in instanceof check, but got 1", TypeError);
+}, "Expecting an object in instanceof check", TypeError);
 
 // kInstanceofNonobjectProto
 test(function() {
@@ -305,12 +305,6 @@
   (1).a = 1;
 }, "Cannot create property 'a' on number '1'", TypeError);
 
-// kStrongImplicitCast
-test(function() {
-  "use strong";
-  "a" + 1;
-}, "In strong mode, implicit conversions are deprecated", TypeError);
-
 // kSymbolToString
 test(function() {
   "" + Symbol();
@@ -345,6 +339,26 @@
   eval("/a/x.test(\"a\");");
 }, "Invalid regular expression flags", SyntaxError);
 
+//kJsonParseUnexpectedEOS
+test(function() {
+  JSON.parse("{")
+}, "Unexpected end of JSON input", SyntaxError);
+
+// kJsonParseUnexpectedTokenAt
+test(function() {
+  JSON.parse("/")
+}, "Unexpected token / in JSON at position 0", SyntaxError);
+
+// kJsonParseUnexpectedTokenNumberAt
+test(function() {
+  JSON.parse("{ 1")
+}, "Unexpected number in JSON at position 2", SyntaxError);
+
+// kJsonParseUnexpectedTokenStringAt
+test(function() {
+  JSON.parse('"""')
+}, "Unexpected string in JSON at position 2", SyntaxError);
+
 // kMalformedRegExp
 test(function() {
   /(/.test("a");
@@ -355,27 +369,6 @@
   new Function(")", "");
 }, "Function arg string contains parenthesis", SyntaxError);
 
-// kUnexpectedEOS
-test(function() {
-  JSON.parse("{")
-}, "Unexpected end of input", SyntaxError);
-
-// kUnexpectedToken
-test(function() {
-  JSON.parse("/")
-}, "Unexpected token /", SyntaxError);
-
-// kUnexpectedTokenNumber
-test(function() {
-  JSON.parse("{ 1")
-}, "Unexpected number", SyntaxError);
-
-// kUnexpectedTokenString
-test(function() {
-  JSON.parse('"""')
-}, "Unexpected string", SyntaxError);
-
-
 // === ReferenceError ===
 
 // kNotDefined
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 95e8da1..cbeee7f 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -43,6 +43,9 @@
   # This test non-deterministically runs out of memory on Windows ia32.
   'regress/regress-crbug-160010': [SKIP],
 
+  # Issue 4698: not fully supported by Turbofan yet
+  'es6/tail-call': [PASS, NO_VARIANTS],
+
   # Issue 3389: deopt_every_n_garbage_collections is unsafe
   'regress/regress-2653': [SKIP],
 
@@ -118,7 +121,18 @@
   'debug-listbreakpoints': [PASS, NO_VARIANTS],  # arm64 nosnap with turbofan
   'debug-enable-disable-breakpoints': [PASS, NO_VARIANTS],  #arm64 nosnap with turbofan.
 
-  # TODO(rossberg)
+  # Issue 3956: Strong mode is deprecating. The expectations inside the
+  # following tests should be updated once deprecation is complete.
+  'strong/destructuring': [SKIP],
+  'strong/implicit-conversions': [SKIP],
+  'strong/implicit-conversions-count': [SKIP],
+  'strong/implicit-conversions-inlining': [SKIP],
+  'strong/load-builtins': [SKIP],
+  'strong/load-element': [SKIP],
+  'strong/load-element-mutate-backing-store': [SKIP],
+  'strong/load-property': [SKIP],
+  'strong/load-property-mutate-backing-store': [SKIP],
+  'strong/load-super': [SKIP],
   'strong/literals': [SKIP], # Rest arguments do not respect strongness in Turbofan.
 
   # Issue 4035: unexpected frame->context() in debugger
@@ -193,7 +207,8 @@
   'regress/regress-crbug-491062': [PASS, NO_VARIANTS],
 
   # Issue 488: this test sometimes times out.
-  'array-constructor': [PASS, TIMEOUT],
+  # TODO(arm): This seems to flush out a bug on arm with simulator.
+  'array-constructor': [PASS, TIMEOUT, ['arch == arm and simulator == True', SKIP]],
 
   # Issue 4413: this test sometimes times out with TSAN because we trigger
   # the slow path in C++ with holey arrays in Function.prototype.apply.
@@ -281,11 +296,16 @@
   'readonly': [PASS, SLOW],
   'regress/regress-1200351': [PASS, ['mode == debug', SLOW]],
   'regress/regress-crbug-474297': [PASS, ['mode == debug', SLOW]],
-  'strong/implicit-conversions': [PASS, SLOW],
-  'strong/load-element-mutate-backing-store': [PASS, SLOW],
 
-  # TODO(bradnelson): Enable tests in a separate change.
-  'wasm/*': [SKIP],
+  # TODO(titzer): correct WASM adapter frame alignment on arm64
+  'wasm/*': [PASS, ['arch == arm64', SKIP]],
+  'wasm/asm-wasm': [PASS, ['arch == arm or arch == arm64', SKIP]],
+
+  # 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]],
+  # desugaring regexp property class relies on ICU.
+  'harmony/unicode-regexp-property-class': [PASS, ['no_i18n == True', FAIL]],
 }],  # ALWAYS
 
 ['novfp3 == True', {
@@ -362,6 +382,9 @@
 
   # BUG(v8:3097)
   'debug-references': [SKIP],
+
+  # BUG(v8:4754).
+  'debug-referenced-by': [PASS, NO_VARIANTS],
 }],  # 'gc_stress == True'
 
 ##############################################################################
@@ -376,6 +399,8 @@
   'asm/embenchen/*': [SKIP],
   'asm/poppler/*': [SKIP],
   'asm/sqlite3/*': [SKIP],
+  # TODO(mips-team): Fix Wasm for big-endian.
+  'wasm/*': [SKIP],
 }],  # 'byteorder == big'
 
 ##############################################################################
@@ -578,6 +603,7 @@
 ['arch == x87', {
   # Turbofan will hit the known issue that x87 changes sNaN to qNaN by default.
   'regress/regress-undefined-nan': [SKIP],
+  'regress/regress-crbug-242924': [SKIP],
 }],  # 'arch == x87'
 
 ##############################################################################
@@ -727,6 +753,7 @@
 
   # Skip tests that are known to be non-deterministic.
   'd8-worker-sharedarraybuffer': [SKIP],
+  'd8-os': [SKIP],
 }],  # 'predictable == True'
 
 ##############################################################################
@@ -737,377 +764,149 @@
 }],  # 'arch == ppc and simulator_run == True'
 
 ['ignition == True', {
-  'const*': [SKIP],
-  'debug-*': [SKIP],
-  'es6/*': [SKIP],
-  'es7/*': [SKIP],
+  # Skip strong mode tests since strong mode is unsupported on ignition.
   'strong/*': [SKIP],
-  'harmony/*': [SKIP],
+
+  # TODO(yangguo,4690): Requires debugger support.
+  'es6/debug*': [SKIP],
+  'harmony/debug*': [SKIP],
   'regress/debug*': [SKIP],
   'regress/regress-debug*': [SKIP],
 
-  # TODO(bradnelson): Figure out why these tests fail with ignition.
-  'wasm/*': [SKIP],
+  # TODO(yangguo,4690): assertion failures in debugger tests.
+  'debug-allscopes-on-debugger': [FAIL],
+  'debug-liveedit-restart-frame': [FAIL],
+  'debug-return-value': [FAIL],
+  'debug-liveedit-literals': [FAIL],
+  'debug-liveedit-3': [FAIL],
+  'debug-liveedit-1': [FAIL],
+  'debug-step-into-json': [FAIL],
+  'debug-liveedit-patch-positions-replace': [FAIL],
+  'debug-step-into-valueof': [FAIL],
+  'debug-liveedit-patch-positions': [FAIL],
+  'debug-liveedit-stepin': [FAIL],
+  'debug-step-4': [FAIL],
+  'debug-liveedit-newsource': [FAIL],
+  'debug-liveedit-stack-padding': [FAIL],
+  'debug-stepframe': [FAIL],
+  'debug-negative-break-points': [FAIL],
+  'debug-stepin-accessor': [FAIL],
+  'debug-step-stub-callfunction': [FAIL],
+  'debug-liveedit-breakpoints': [FAIL],
+  'debug-stepin-accessor-ic': [FAIL],
+  'debug-stepin-builtin': [FAIL],
+  'debug-stepin-foreach': [FAIL],
+  'debug-stepnext-do-while': [FAIL],
+  'debug-stepin-builtin-callback-opt': [FAIL],
+  'debug-stepin-function-call': [FAIL],
 
-  'allocation-folding': [SKIP],
-  'api-call-after-bypassed-exception': [SKIP],
-  'apply-arguments-gc-safepoint': [SKIP],
-  'arguments-load-across-eval': [SKIP],
-  'arguments-read-and-assignment': [SKIP],
-  'array-bounds-check-removal': [SKIP],
-  'array-elements-from-array-prototype-chain': [SKIP],
-  'array-functions-prototype-misc': [SKIP],
-  'array-join': [SKIP],
-  'array-literal-feedback': [SKIP],
+  # TODO(yangguo,4690): Check failure in debug.cc BreakLocation::SetBreakPoint
+  # DCHECK(IsDebugBreak() || IsDebuggerStatement());
+  'regress/regress-1523': [FAIL],
+  'regress/regress-102153': [FAIL],
+  'regress/regress-2825': [FAIL],
+  'regress/regress-crbug-119800': [FAIL],
+  'regress/regress-crbug-467180': [FAIL],
+  'regress/regress-opt-after-debug-deopt': [FAIL],
+
+  # TODO(rmcilroy,4681): Requires support for generators.
+  'messages': [FAIL],
+  'es6/array-from': [FAIL],
+  'regress-3225': [FAIL],
+  'es6/classes-subclass-builtins': [FAIL],
+  'es6/computed-property-names-classes': [FAIL],
+  'es6/computed-property-names-object-literals-methods': [FAIL],
+  'es6/function-length-configurable': [FAIL],
+  'es6/generators-poisoned-properties': [FAIL],
+  'es6/generators-runtime': [FAIL],
+  'es6/generators-objects': [FAIL],
+  'es6/generators-parsing': [FAIL],
+  'es6/generators-iteration': [FAIL],
+  'es6/generators-states': [FAIL],
+  'es6/iteration-semantics': [FAIL],
+  'es6/iterator-prototype': [FAIL],
+  'es6/generators-mirror': [FAIL],
+  'es6/object-literals-method': [FAIL],
+  'es6/object-literals-super': [FAIL],
+  'es6/generators-relocation': [FAIL],
+  'es6/spread-array': [FAIL],
+  'es6/generators-debug-liveedit': [FAIL],
+  'es6/spread-call': [FAIL],
+  'es6/typedarray-from': [FAIL],
+  'es6/typedarray': [FAIL],
+  'es6/regress/regress-2681': [FAIL],
+  'es6/regress/regress-2691': [FAIL],
+  'es6/regress/regress-3280': [FAIL],
+  'harmony/destructuring-assignment': [FAIL],
+  'harmony/function-sent': [FAIL],
+  'harmony/reflect-enumerate-delete': [FAIL],
+  'harmony/reflect-enumerate-special-cases': [FAIL],
+  'harmony/proxies-enumerate': [FAIL],
+  'harmony/reflect-enumerate-opt': [FAIL],
+  'harmony/reflect-enumerate': [FAIL],
+  'harmony/destructuring': [FAIL],
+  'harmony/regress/regress-4482': [FAIL],
+  'harmony/generators': [FAIL],
+  'harmony/iterator-close': [FAIL],
+  'harmony/reflect-construct': [FAIL],
+  'es6/promises': [FAIL],
+
+  # TODO(rmcilroy,4680): Check failed in
+  # BytecodeGenerator::VisitFunctionLiteral - !shared_info.is_null().
+  'regress/regress-crbug-429159': [FAIL],
+
+  # TODO(rmcilroy,4680): Pass on debug, fail on release.
+  'compiler/regress-stacktrace-methods': [PASS, ['mode == release', FAIL]],
+
+  # TODO(rmcilroy,4680): Test assert failures.
+  'array-literal-feedback': [FAIL],
+  'undetectable-compare': [FAIL],
+  'debug-liveedit-2': [FAIL],
+  'es6/string-search': [FAIL],
+  'es6/mirror-collections': [FAIL],
+  'es6/regress/regress-468661': [FAIL],
+  'harmony/string-replace': [FAIL],
+  'harmony/string-match': [FAIL],
+  'harmony/string-split': [FAIL],
+  'regress/regress-2618': [FAIL],
+  'regress/regress-4121': [FAIL],
+  'regress/regress-4266': [FAIL],
+  'harmony/simd': [FAIL],
+  'regress/regress-crbug-109362': [FAIL],
+  'regress/regress-crbug-568477-2': [FAIL],
+  'regress/regress-crbug-568477-3': [FAIL],
+  'regress/regress-crbug-568477-1': [FAIL],
+  'regress/regress-2318': [FAIL],
+
+  # TODO(rmcilroy, 4680): new ES6 instanceof support
+  'harmony/instanceof-es6': [SKIP],
+
+  # TODO(rmcilroy,4680): Test timeouts.
   'array-literal-transitions': [SKIP],
-  'array-tostring': [SKIP],
-  'break': [SKIP],
-  'call-runtime-tail': [SKIP],
-  'compiler/compare-map-elim2': [SKIP],
-  'compiler/deopt-inlined-smi': [SKIP],
-  'compiler/deopt-tonumber-compare': [SKIP],
-  'compiler/escape-analysis-arguments': [SKIP],
-  'compiler/escape-analysis': [SKIP],
-  'compiler/expression-trees': [SKIP],
-  'compiler/inline-arguments': [SKIP],
-  'compiler/inline-arity-mismatch': [SKIP],
-  'compiler/inline-construct': [SKIP],
-  'compiler/lazy-deopt-in-literal': [SKIP],
-  'compiler/manual-concurrent-recompile': [SKIP],
-  'compiler/optimized-for-in': [SKIP],
-  'compiler/optimized-function-calls': [SKIP],
-  'compiler/optimize_max': [SKIP],
-  'compiler/optimize_min': [SKIP],
-  'compiler/opt-next-call-turbo': [SKIP],
-  'compiler/osr-forof': [SKIP],
-  'compiler/property-refs': [SKIP],
-  'compiler/regress-3786': [SKIP],
-  'compiler/regress-446647': [SKIP],
-  'compiler/regress-447567': [SKIP],
-  'compiler/regress-469089': [SKIP],
-  'compiler/regress-96989': [SKIP],
-  'compiler/regress-const': [SKIP],
-  'compiler/regress-funarguments': [SKIP],
-  'compiler/regress-stacktrace-methods': [SKIP],
-  'compiler/regress-variable-liveness': [SKIP],
-  'compiler/rotate': [SKIP],
-  'compiler/safepoint': [SKIP],
-  'compiler/try-deopt': [SKIP],
-  'compiler/try-osr': [SKIP],
-  'compiler/uint32': [SKIP],
-  'compiler/variables': [SKIP],
-  'context-calls-maintained': [SKIP],
-  'contextual-calls': [SKIP],
-  'cross-realm-filtering': [SKIP],
-  'cyclic-array-to-string': [SKIP],
-  'd8-worker-sharedarraybuffer': [SKIP],
-  'delete-in-with': [SKIP],
-  'deopt-minus-zero': [SKIP],
-  'deserialize-optimize-inner': [SKIP],
-  'double-equals': [SKIP],
-  'eval-enclosing-function-name': [SKIP],
-  'eval-stack-trace': [SKIP],
-  'fast-prototype': [SKIP],
-  'field-type-tracking': [SKIP],
-  'for-in-opt': [SKIP],
-  'for-in-special-cases': [SKIP],
-  'function-call': [SKIP],
-  'get-caller-js-function': [SKIP],
-  'get-prototype-of': [SKIP],
-  'getter-in-prototype': [SKIP],
-  'global-hash': [SKIP],
-  'global-load-from-eval-in-with': [SKIP],
-  'global-vars-with': [SKIP],
-  'instanceof-2': [SKIP],
-  'json-replacer-number-wrapper-tostring': [SKIP],
-  'json-replacer-order': [SKIP],
-  'json': [SKIP],
-  'keyed-load-with-symbol-key': [SKIP],
-  'local-load-from-eval': [SKIP],
-  'math-min-max': [SKIP],
-  'messages': [SKIP],
-  'mirror-object': [SKIP],
-  'object-literal-gc': [SKIP],
-  'osr-elements-kind': [SKIP],
-  'property-load-across-eval': [SKIP],
-  'proto-accessor': [SKIP],
-  'readonly': [SKIP],
-  'receiver-in-with-calls': [SKIP],
-  'regress-3225': [SKIP],
-  'regress/clear-keyed-call': [SKIP],
-  'regress/poly_count_operation': [SKIP],
-  'regress/regress-102153': [SKIP],
-  'regress/regress-1030466': [SKIP],
-  'regress/regress-1079': [SKIP],
-  'regress/regress-109195': [SKIP],
-  'regress/regress-1114040': [SKIP],
-  'regress/regress-1125': [SKIP],
-  'regress/regress-1129': [SKIP],
-  'regress/regress-1170187': [SKIP],
-  'regress/regress-117409': [SKIP],
-  'regress/regress-1177809': [SKIP],
-  'regress/regress-119609': [SKIP],
-  'regress/regress-123919': [SKIP],
-  'regress/regress-124594': [SKIP],
-  'regress/regress-125515': [SKIP],
-  'regress/regress-128018': [SKIP],
-  'regress/regress-131994': [SKIP],
-  'regress/regress-133211b': [SKIP],
-  'regress/regress-1365': [SKIP],
-  'regress/regress-1369': [SKIP],
-  'regress/regress-1403': [SKIP],
-  'regress/regress-1412': [SKIP],
-  'regress/regress-1436': [SKIP],
-  'regress/regress-1493017': [SKIP],
-  'regress/regress-1523': [SKIP],
-  'regress/regress-1560': [SKIP],
-  'regress/regress-1586': [SKIP],
-  'regress/regress-1639-2': [SKIP],
-  'regress/regress-1639': [SKIP],
-  'regress/regress-166553': [SKIP],
-  'regress/regress-1708': [SKIP],
-  'regress/regress-1757': [SKIP],
-  'regress/regress-1790': [SKIP],
-  'regress/regress-1853': [SKIP],
-  'regress/regress-1980': [SKIP],
-  'regress/regress-2054': [SKIP],
-  'regress/regress-2071': [SKIP],
-  'regress/regress-2163': [SKIP],
-  'regress/regress-220': [SKIP],
-  'regress/regress-2318': [SKIP],
-  'regress/regress-2339': [SKIP],
-  'regress/regress-2374': [SKIP],
-  'regress/regress-2593': [SKIP],
-  'regress/regress-2618': [SKIP],
-  'regress/regress-263': [SKIP],
-  'regress/regress-265': [SKIP],
-  'regress/regress-269': [SKIP],
-  'regress/regress-2790': [SKIP],
-  'regress/regress-2825': [SKIP],
-  'regress/regress-3135': [SKIP],
-  'regress/regress-3138': [SKIP],
-  'regress/regress-318420': [SKIP],
-  'regress/regress-320532': [SKIP],
-  'regress/regress-3281': [SKIP],
-  'regress/regress-331444': [SKIP],
-  'regress/regress-343609': [SKIP],
-  'regress/regress-347530': [SKIP],
-  'regress/regress-347914': [SKIP],
-  'regress/regress-351261': [SKIP],
-  'regress/regress-352982': [SKIP],
-  'regress/regress-353551': [SKIP],
-  'regress/regress-354357': [SKIP],
-  'regress/regress-356053': [SKIP],
-  'regress/regress-357105': [SKIP],
-  'regress/regress-359441': [SKIP],
-  'regress/regress-361025': [SKIP],
-  'regress/regress-3621': [SKIP],
-  'regress/regress-365172-3': [SKIP],
-  'regress/regress-370827': [SKIP],
-  'regress/regress-377290': [SKIP],
-  'regress/regress-3859': [SKIP],
-  'regress/regress-3884': [SKIP],
-  'regress/regress-3926': [SKIP],
-  'regress/regress-3960': [SKIP],
-  'regress/regress-3969': [SKIP],
-  'regress/regress-3985': [SKIP],
-  'regress/regress-4023': [SKIP],
-  'regress/regress-4027': [SKIP],
-  'regress/regress-403292': [SKIP],
-  'regress/regress-410912': [SKIP],
-  'regress/regress-4121': [SKIP],
-  'regress/regress-419663': [SKIP],
-  'regress/regress-4255-4': [SKIP],
-  'regress/regress-430201b': [SKIP],
-  'regress/regress-430201': [SKIP],
-  'regress/regress-4309-3': [SKIP],
-  'regress/regress-4320': [SKIP],
-  'regress/regress-4325': [SKIP],
-  'regress/regress-436893': [SKIP],
-  'regress/regress-4374': [SKIP],
-  'regress/regress-4388': [SKIP],
-  'regress/regress-444805': [SKIP],
-  'regress/regress-446389': [SKIP],
-  'regress/regress-447756': [SKIP],
-  'regress/regress-4515': [SKIP],
-  'regress/regress-4521': [SKIP],
-  'regress/regress-4525': [SKIP],
-  'regress/regress-453481': [SKIP],
-  'regress/regress-4534': [SKIP],
-  'regress/regress-454725': [SKIP],
-  'regress/regress-457935': [SKIP],
-  'regress/regress-470804': [SKIP],
-  'regress/regress-476488': [SKIP],
-  'regress/regress-503565': [SKIP],
-  'regress/regress-514362': [SKIP],
-  'regress/regress-520029': [SKIP],
-  'regress/regress-542100': [SKIP],
-  'regress/regress-544991': [SKIP],
-  'regress/regress-568765': [SKIP],
-  'regress/regress-572589': [SKIP],
-  'regress/regress-580': [SKIP],
-  'regress/regress-618': [SKIP],
-  'regress/regress-69': [SKIP],
-  'regress/regress-70066': [SKIP],
-  'regress/regress-747': [SKIP],
-  'regress/regress-753': [SKIP],
-  'regress/regress-799761': [SKIP],
-  'regress/regress-806473': [SKIP],
-  'regress/regress-842017': [SKIP],
-  'regress/regress-84234': [SKIP],
-  'regress/regress-88858': [SKIP],
-  'regress/regress-94425': [SKIP],
-  'regress/regress-94873': [SKIP],
-  'regress/regress-95485': [SKIP],
-  'regress/regress-97116b': [SKIP],
-  'regress/regress-97116': [SKIP],
-  'regress/regress-974': [SKIP],
-  'regress/regress-99167': [SKIP],
-  'regress/regress-998565': [SKIP],
-  'regress/regress-arg-materialize-store': [SKIP],
-  'regress/regress-arguments-gc': [SKIP],
-  'regress/regress-assignment-in-test-context': [SKIP],
-  'regress/regress-bce-underflow': [SKIP],
-  'regress/regress-cnlt-elements': [SKIP],
-  'regress/regress-cnlt-enum-indices': [SKIP],
-  'regress/regress-cntl-descriptors-enum': [SKIP],
-  'regress/regress-conditional-position': [SKIP],
-  'regress/regress-convert-enum': [SKIP],
-  'regress/regress-crbug-109362': [SKIP],
-  'regress/regress-crbug-119800': [SKIP],
-  'regress/regress-crbug-163530': [SKIP],
-  'regress/regress-crbug-229923': [SKIP],
-  'regress/regress-crbug-242502': [SKIP],
-  'regress/regress-crbug-242924': [SKIP],
-  'regress/regress-crbug-245480': [SKIP],
-  'regress/regress-crbug-350864': [SKIP],
-  'regress/regress-crbug-351262': [SKIP],
-  'regress/regress-crbug-352058': [SKIP],
-  'regress/regress-crbug-357137': [SKIP],
-  'regress/regress-crbug-385002': [SKIP],
-  'regress/regress-crbug-387599': [SKIP],
-  'regress/regress-crbug-405517': [SKIP],
-  'regress/regress-crbug-405922': [SKIP],
-  'regress/regress-crbug-409614': [SKIP],
-  'regress/regress-crbug-410033': [SKIP],
-  'regress/regress-crbug-412208': [SKIP],
-  'regress/regress-crbug-416558': [SKIP],
-  'regress/regress-crbug-424142': [SKIP],
-  'regress/regress-crbug-429159': [SKIP],
-  'regress/regress-crbug-431602': [SKIP],
-  'regress/regress-crbug-432493': [SKIP],
-  'regress/regress-crbug-450642': [SKIP],
-  'regress/regress-crbug-455644': [SKIP],
-  'regress/regress-crbug-465298': [SKIP],
-  'regress/regress-crbug-467180': [SKIP],
-  'regress/regress-crbug-467531': [SKIP],
-  'regress/regress-crbug-474297': [SKIP],
-  'regress/regress-crbug-480819': [SKIP],
-  'regress/regress-crbug-481896': [SKIP],
-  'regress/regress-crbug-485548-1': [SKIP],
-  'regress/regress-crbug-485548-2': [SKIP],
-  'regress/regress-crbug-487289': [SKIP],
-  'regress/regress-crbug-489293': [SKIP],
-  'regress/regress-crbug-489597': [SKIP],
-  'regress/regress-crbug-498142': [SKIP],
-  'regress/regress-crbug-501809': [SKIP],
-  'regress/regress-crbug-506443': [SKIP],
-  'regress/regress-crbug-507070': [SKIP],
   'regress/regress-crbug-517592': [SKIP],
-  'regress/regress-crbug-522895': [SKIP],
-  'regress/regress-crbug-527364': [SKIP],
-  'regress/regress-crbug-546968': [SKIP],
-  'regress/regress-crbug-568477-1': [SKIP],
-  'regress/regress-crbug-568477-2': [SKIP],
-  'regress/regress-crbug-568477-3': [SKIP],
   'regress/regress-crbug-568477-4': [SKIP],
-  'regress/regress-crbug-572590': [SKIP],
-  'regress/regress-crbug-573857': [SKIP],
-  'regress/regress-crbug-575080': [SKIP],
-  'regress/regress-deopt-gcb': [SKIP],
-  'regress/regress-deopt-gc': [SKIP],
-  'regress/regress-deopt-in-array-literal-spread': [SKIP],
-  'regress/regress-embedded-cons-string': [SKIP],
-  'regress/regress-existing-shared-function-info': [SKIP],
-  'regress/regress-fast-literal-transition': [SKIP],
-  'regress/regress-function-constructor-receiver': [SKIP],
-  'regress/regress-handle-illegal-redeclaration': [SKIP],
-  'regress/regress-inline-class-constructor': [SKIP],
-  'regress/regress-inlining-function-literal-context': [SKIP],
-  'regress/regress-latin-1': [SKIP],
-  'regress/regress-lazy-deopt-reloc': [SKIP],
-  'regress/regress-opt-after-debug-deopt': [SKIP],
-  'regress/regress-osr-in-case-label': [SKIP],
-  'regress/regress-osr-in-literal': [SKIP],
-  'regress/regress-prepare-break-while-recompile': [SKIP],
-  'regress/regress-put-prototype-transition': [SKIP],
-  'regress/regress-sliced-external-cons-regexp': [SKIP],
-  'regress/regress-store-heapobject': [SKIP],
-  'regress/regress-transcendental': [SKIP],
-  'regress/regress-typedarray-length': [SKIP],
-  'regress/splice-missing-wb': [SKIP],
-  'setter-on-constructor-prototype': [SKIP],
-  'shift-for-integer-div': [SKIP],
-  'simple-constructor': [SKIP],
-  'sparse-array-reverse': [SKIP],
-  'stack-traces': [SKIP],
-  'strict-mode': [SKIP],
-  'string-case': [SKIP],
-  'string-external-cached': [SKIP],
-  'string-externalize': [SKIP],
-  'string-natives': [SKIP],
-  'string-replace-with-empty': [SKIP],
-  'string-slices': [SKIP],
-  'tools/profile': [SKIP],
-  'tools/profviz': [SKIP],
-  'try-finally-continue': [SKIP],
-  'try': [SKIP],
-  'undetectable-compare': [SKIP],
-  'unused-context-in-with': [SKIP],
-  'value-wrapper': [SKIP],
-  'with-function-expression': [SKIP],
-  'with-parameter-access': [SKIP],
-  'with-prototype': [SKIP],
-  'with-readonly': [SKIP],
-  'with-value': [SKIP],
-  'regress/regress-builtinbust-7': [SKIP],
-  'regress/regress-crbug-451770': [SKIP],
-  'regress/regress-crbug-503968': [SKIP],
-  'regress/regress-crbug-504729': [SKIP],
+  'regress/regress-crbug-409614': [SKIP],
+  'regress/regress-crbug-42414': [SKIP],
+  'regress/regress-1853': [SKIP],
+  'regress/regress-crbug-424142': [SKIP],
 }],  # ignition == True
 
+['ignition == True and arch == arm64', {
+  # TODO(rmcilroy,4680): Fails on Arm64 due to expecting to take less than 3
+  # seconds.
+  'regress/regress-165637': [FAIL],
+}],  # ignition == True and arch == arm64
+
 ['ignition == True and (arch == arm or arch == arm64)', {
-  'array-constructor': [SKIP],
-  'array-sort': [SKIP],
-  'array-store-and-grow': [SKIP],
-  'compiler/division-by-constant': [SKIP],
-  'compiler/osr-big': [SKIP],
+  # TODO(rmcilroy,4680): Arm / Arm64 specific timeouts.
+  'asm/construct-double': [SKIP],
   'compiler/osr-nested': [SKIP],
   'compiler/osr-one': [SKIP],
   'compiler/osr-two': [SKIP],
-  'mul-exhaustive-part*': [SKIP],
   'regress/regress-1257': [SKIP],
   'regress/regress-165637': [SKIP],
-  'regress/regress-319722-ArrayBuffer': [SKIP],
-  'regress/regress-411210': [SKIP],
+  'regress/regress-2185': [SKIP],
   'regress/regress-91008': [SKIP],
-  'regress/regress-crbug-347903': [SKIP],
-  'regress/regress-crbug-500497': [SKIP],
-  'regress/regress-crbug-505007-1': [SKIP],
-  'regress/regress-crbug-505007-2': [SKIP],
-  'regress/regress-2193': [SKIP],
-  'regress/regress-3158': [SKIP],
-  'regress/regress-347904': [SKIP],
-  'regress/regress-380092': [SKIP],
-  'regress/regress-4173': [SKIP],
-  'regress/regress-copy-hole-to-field': [SKIP],
-  'regress/regress-crbug-315252': [SKIP],
-  'regress/regress-crbug-412215': [SKIP],
-  'regress/regress-crbug-513507': [SKIP],
-  'regress/regress-deep-proto': [SKIP],
-  'regress/regress-deopt-store-effect': [SKIP],
-  'regress/regress-undefined-store-keyed-fast-element': [SKIP],
-  'stack-traces-overflow': [SKIP],
   'unicodelctest': [SKIP],
   'unicodelctest-no-optimization': [SKIP],
 }],  # ignition == True and (arch == arm or arch == arm64)
@@ -1118,6 +917,9 @@
   'array-functions-prototype-misc': [SKIP],
   'strong/implicit-conversions': [SKIP],
   'strong/load-element-mutate-backing-store': [SKIP],
+
+  # Stack overflow.
+  'big-array-literal': [SKIP],
 }],  # 'gcov_coverage'
 
 ]
diff --git a/test/mjsunit/random-bit-correlations.js b/test/mjsunit/random-bit-correlations.js
index 8322cfa..2ac84c5 100644
--- a/test/mjsunit/random-bit-correlations.js
+++ b/test/mjsunit/random-bit-correlations.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: --random-seed=12 --nostress-opt --noalways-opt --predictable
+// Flags: --random-seed=20 --nostress-opt --noalways-opt --predictable
 
 (function() {
   var kHistory = 2;
diff --git a/test/mjsunit/regexp-compile.js b/test/mjsunit/regexp-compile.js
index 6a24325..92c3f7b 100644
--- a/test/mjsunit/regexp-compile.js
+++ b/test/mjsunit/regexp-compile.js
@@ -40,3 +40,5 @@
 re.compile("(y)");
 
 assertEquals(["y", "y"], re.exec("axyb"));
+
+assertEquals(2, re.compile.length);
diff --git a/test/mjsunit/regexp.js b/test/mjsunit/regexp.js
index b6f019e..1a5de2a 100644
--- a/test/mjsunit/regexp.js
+++ b/test/mjsunit/regexp.js
@@ -719,9 +719,6 @@
 assertThrows("RegExp.prototype.toString.call('')", TypeError);
 assertThrows("RegExp.prototype.toString.call(false)", TypeError);
 assertThrows("RegExp.prototype.toString.call(true)", TypeError);
-assertThrows("RegExp.prototype.toString.call([])", TypeError);
-assertThrows("RegExp.prototype.toString.call({})", TypeError);
-assertThrows("RegExp.prototype.toString.call(function(){})", TypeError);
 
 // Test mutually recursive capture and backreferences.
 assertEquals(["b", "", ""], /(\2)b(\1)/.exec("aba"));
diff --git a/test/mjsunit/regress-587004.js b/test/mjsunit/regress-587004.js
new file mode 100644
index 0000000..9dc6052
--- /dev/null
+++ b/test/mjsunit/regress-587004.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-gc --min-semi-space-size=32
+
+// We need to set --min-semi-space-size to enable allocation site pretenuring.
+
+function foo(i) {
+  with({}) {};
+  x = {};
+  x.a = 0.23;
+  x.b = 0.3;
+  return x;
+}
+
+var all = [];
+function step() {
+  for (var i = 0; i < 100; i++) {
+    var z = foo(i);
+    // Write unboxed double in object slack.
+    z.c = 0.1 + z.b
+    all.push(z);
+  }
+  gc(1);
+  gc(1);
+}
+
+step();
+// Now foo will allocate objects in old space.
+step();
diff --git a/test/mjsunit/regress/math-min.js b/test/mjsunit/regress/math-min.js
new file mode 100644
index 0000000..942e9d0
--- /dev/null
+++ b/test/mjsunit/regress/math-min.js
@@ -0,0 +1,66 @@
+// Copyright 2016 the V8 project 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(4);
+a[2] *= -1;
+a[3] *= -1;
+assertEquals(0, a[0]);
+assertEquals(0, a[1]);
+assertEquals(-0, a[2]);
+assertEquals(-0, a[3]);
+
+function f1() {
+  var z = a[0];
+  // Same register.
+  assertEquals(0, Math.min(z, z));
+}
+
+function f2() {
+  // Different registers.
+  assertEquals(0, Math.min(a[0], a[1]));
+}
+
+function f3() {
+  // Zero and minus zero.
+  assertEquals(-0, Math.min(a[1], a[2]));
+}
+
+function f4() {
+  // Zero and minus zero, reversed order.
+  assertEquals(-0, Math.min(a[2], a[1]));
+}
+
+function f5() {
+  // Minus zero, same register.
+  var m_z = a[2];
+  assertEquals(-0, Math.min(m_z, m_z));
+}
+
+function f6() {
+  // Minus zero, different registers.
+  assertEquals(-0, Math.min(a[2], a[3]));
+}
+
+for (var i = 0; i < 3; i++) {
+  f1();
+  f2();
+  f3();
+  f4();
+  f5();
+  f6();
+}
+%OptimizeFunctionOnNextCall(f1);
+%OptimizeFunctionOnNextCall(f2);
+%OptimizeFunctionOnNextCall(f3);
+%OptimizeFunctionOnNextCall(f4);
+%OptimizeFunctionOnNextCall(f5);
+%OptimizeFunctionOnNextCall(f6);
+f1();
+f2();
+f3();
+f4();
+f5();
+f6();
diff --git a/test/mjsunit/regress/regress-3650-1.js b/test/mjsunit/regress/regress-3650-1.js
new file mode 100644
index 0000000..db91ec2
--- /dev/null
+++ b/test/mjsunit/regress/regress-3650-1.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 --deopt-every-n-times=55
+// Flags: --nodead-code-elimination
+
+function f(t) {
+  var result = [];
+  for (var i in t) {
+    for (var j in t) {
+      result.push(i + j + t[i] + t[j]);
+      continue;
+    }
+  }
+  return result.join('');
+}
+
+var t = {a: "1", b: "2"};
+assertEquals("aa11ab12ba21bb22", f(t));
+%OptimizeFunctionOnNextCall(f);
+assertEquals("aa11ab12ba21bb22", f(t));
diff --git a/test/mjsunit/regress/regress-3650-2.js b/test/mjsunit/regress/regress-3650-2.js
new file mode 100644
index 0000000..aaa6d55
--- /dev/null
+++ b/test/mjsunit/regress/regress-3650-2.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: --allow-natives-syntax
+
+var a = {}
+var b = {}
+a.x = 1;
+a.y = 1;
+b.x = 1;
+
+function foo(c) {
+  var s = 0;
+  for (var p in c) { s++; }
+  return s;
+}
+
+assertEquals(2, foo(a));
+assertEquals(1, foo(b));
+%OptimizeFunctionOnNextCall(foo);
+assertEquals(2, foo(a));
+assertEquals(1, foo(b));
diff --git a/test/mjsunit/regress/regress-3650-3.js b/test/mjsunit/regress/regress-3650-3.js
new file mode 100644
index 0000000..013e4df
--- /dev/null
+++ b/test/mjsunit/regress/regress-3650-3.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 foo(a) {
+  for (var d in a) {
+    delete a[1];
+  }
+}
+
+foo([1,2,3]);
+foo([2,3,4]);
+%OptimizeFunctionOnNextCall(foo);
+foo([1,2,3]);
+assertOptimized(foo);
diff --git a/test/mjsunit/regress/regress-4267.js b/test/mjsunit/regress/regress-4267.js
new file mode 100644
index 0000000..f8cf746
--- /dev/null
+++ b/test/mjsunit/regress/regress-4267.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
+
+"use strict";
+
+var a = [];
+Object.defineProperty(a, "0", {configurable: false, value: 10});
+assertEquals(1, a.length);
+var setter = ()=>{ a.length = 0; };
+assertThrows(setter);
+assertThrows(setter);
+%OptimizeFunctionOnNextCall(setter);
+assertThrows(setter);
diff --git a/test/mjsunit/regress/regress-4509-Class-constructor-typeerror-realm.js b/test/mjsunit/regress/regress-4509-Class-constructor-typeerror-realm.js
new file mode 100644
index 0000000..bc83a11
--- /dev/null
+++ b/test/mjsunit/regress/regress-4509-Class-constructor-typeerror-realm.js
@@ -0,0 +1,25 @@
+// 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";
+var realm = Realm.create();
+var OtherTypeError = Realm.eval(realm, 'TypeError');
+
+class Derived extends Object {
+  constructor() {
+    return null;
+  }
+}
+
+assertThrows(() => { new Derived() }, TypeError);
+
+var OtherDerived = Realm.eval(realm,
+   "'use strict';" +
+   "class Derived extends Object {" +
+      "constructor() {" +
+        "return null;" +
+      "}};");
+
+// Before throwing the TypeError we have to switch to the caller context.
+assertThrows(() => { new OtherDerived() }, TypeError);
diff --git a/test/mjsunit/regress/regress-4654.js b/test/mjsunit/regress/regress-4654.js
new file mode 100644
index 0000000..eb08b11
--- /dev/null
+++ b/test/mjsunit/regress/regress-4654.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.
+
+assertEquals('hello\u0000foobar', 'hello\u0000foobar'.normalize('NFC'));
diff --git a/test/mjsunit/regress/regress-4659.js b/test/mjsunit/regress/regress-4659.js
new file mode 100644
index 0000000..ff436be
--- /dev/null
+++ b/test/mjsunit/regress/regress-4659.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: --harmony-function-name
+
+var obj = {
+  get longerName(){
+    return 42;
+  }
+};
+assertEquals(42, obj.longerName);
diff --git a/test/mjsunit/regress/regress-4665-2.js b/test/mjsunit/regress/regress-4665-2.js
new file mode 100644
index 0000000..b94301e
--- /dev/null
+++ b/test/mjsunit/regress/regress-4665-2.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: --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-4693.js b/test/mjsunit/regress/regress-4693.js
index ed832e6..6145964 100644
--- a/test/mjsunit/regress/regress-4693.js
+++ b/test/mjsunit/regress/regress-4693.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-sloppy-function
+// Flags: --harmony-sloppy-function --nolegacy-const
 
 // In sloppy mode we allow function redeclarations within blocks for webcompat.
 (function() {
@@ -27,3 +27,54 @@
     }
   })();
 `, SyntaxError);
+
+// Conflicts between let and function still throw
+assertThrows(`
+  (function() {
+    if (true) {
+      let f;
+      function f() { return 2 }
+    }
+  })();
+`, SyntaxError);
+
+assertThrows(`
+  (function() {
+    if (true) {
+      function f() { return 2 }
+      let f;
+    }
+  })();
+`, SyntaxError);
+
+// Conflicts between const and function still throw
+assertThrows(`
+  (function() {
+    if (true) {
+      const f;
+      function f() { return 2 }
+    }
+  })();
+`, SyntaxError);
+
+assertThrows(`
+  (function() {
+    if (true) {
+      function f() { return 2 }
+      const f;
+    }
+  })();
+`, SyntaxError);
+
+// Annex B redefinition semantics still apply with more blocks
+(function() {
+  assertEquals(undefined, f);  // Annex B
+  if (true) {
+    assertEquals(undefined, f);
+    { function f() { return 1 } }
+    assertEquals(1, f());
+    { function f() { return 2 } }
+    assertEquals(2, f());
+  }
+  assertEquals(2, f());  // Annex B
+})();
diff --git a/test/mjsunit/regress/regress-4715.js b/test/mjsunit/regress/regress-4715.js
new file mode 100644
index 0000000..0e38cdc
--- /dev/null
+++ b/test/mjsunit/regress/regress-4715.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: --allow-natives-syntax --dead-code-elimination --expose-gc
+
+var training = {};
+training.a = "nop";
+training.slow = "nop";
+delete training.slow;  // Dictionary-mode properties => slow-mode for-in.
+
+var keepalive = {};
+keepalive.a = "nop";  // Keep a map early in the transition chain alive.
+
+function GetReal() {
+  var r = {};
+  r.a = "nop";
+  r.b = "nop";
+  r.c = "dictionarize",
+  r.d = "gc";
+  r.e = "result";
+  return r;
+};
+
+function SideEffect(object, action) {
+  if (action === "dictionarize") {
+    delete object.a;
+  } else if (action === "gc") {
+    gc();
+  }
+}
+
+function foo(object) {
+  for (var key in object) {
+    SideEffect(object, object[key]);
+  }
+  return key;
+}
+
+// Collect type feedback for slow-mode for-in.
+foo(training);
+SideEffect({a: 0}, "dictionarize");
+SideEffect({}, "gc");
+
+// Compile for slow-mode objects...
+%OptimizeFunctionOnNextCall(foo);
+// ...and pass in a fast-mode object.
+assertEquals("e", foo(GetReal()));
diff --git a/test/mjsunit/regress/regress-4788-1.js b/test/mjsunit/regress/regress-4788-1.js
new file mode 100644
index 0000000..347ab5e
--- /dev/null
+++ b/test/mjsunit/regress/regress-4788-1.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: --allow-natives-syntax
+
+var f = (function() {
+  "use asm";
+  function foo(x) {
+    return x == 0;
+  }
+  return foo;
+})();
+
+function deopt(f) {
+  return {
+    toString : function() {
+      %DeoptimizeFunction(f);
+      return "2";
+    }
+  };
+}
+
+%OptimizeFunctionOnNextCall(f);
+assertFalse(f(deopt(f)));
diff --git a/test/mjsunit/regress/regress-4788-2.js b/test/mjsunit/regress/regress-4788-2.js
new file mode 100644
index 0000000..5441705
--- /dev/null
+++ b/test/mjsunit/regress/regress-4788-2.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: --allow-natives-syntax
+
+var f = (function() {
+  "use asm";
+  function foo(x) {
+    return x < x;
+  }
+  return foo;
+})();
+
+function deopt(f) {
+  return {
+    toString : function() {
+      %DeoptimizeFunction(f);
+      return "2";
+    }
+  };
+}
+
+%OptimizeFunctionOnNextCall(f);
+assertFalse(f(deopt(f)));
diff --git a/test/mjsunit/regress/regress-4800.js b/test/mjsunit/regress/regress-4800.js
new file mode 100644
index 0000000..af7cbc0
--- /dev/null
+++ b/test/mjsunit/regress/regress-4800.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: --allow-natives-syntax
+
+function f(x, len) {
+  var distraction = [];
+  var result = new Array(25);
+
+  // Create a bunch of double values with long live ranges.
+  var d0 = x + 0.5;
+  var d1 = x + 1.5;
+  var d2 = x + 2.5;
+  var d3 = x + 3.5;
+  var d4 = x + 4.5;
+  var d5 = x + 5.5;
+  var d6 = x + 6.5;
+  var d7 = x + 7.5;
+  var d8 = x + 8.5;
+  var d9 = x + 9.5;
+  var d10 = x + 10.5;
+  var d11 = x + 11.5;
+  var d12 = x + 12.5;
+  var d13 = x + 13.5;
+  var d14 = x + 14.5;
+  var d15 = x + 15.5;
+  var d16 = x + 16.5;
+  var d17 = x + 17.5;
+  var d18 = x + 18.5;
+  var d19 = x + 19.5;
+  var d20 = x + 20.5;
+  var d21 = x + 21.5;
+  var d22 = x + 22.5;
+  var d23 = x + 23.5;
+  var d24 = x + 24.5;
+
+  // Trigger a stub failure when the array grows too big.
+  distraction[len] = 0;
+
+  // Write the long-lived doubles to memory and verify them.
+  result[0] = d0;
+  result[1] = d1;
+  result[2] = d2;
+  result[3] = d3;
+  result[4] = d4;
+  result[5] = d5;
+  result[6] = d6;
+  result[7] = d7;
+  result[8] = d8;
+  result[9] = d9;
+  result[10] = d10;
+  result[11] = d11;
+  result[12] = d12;
+  result[13] = d13;
+  result[14] = d14;
+  result[15] = d15;
+  result[16] = d16;
+  result[17] = d17;
+  result[18] = d18;
+  result[19] = d19;
+  result[20] = d20;
+  result[21] = d21;
+  result[22] = d22;
+  result[23] = d23;
+  result[24] = d24;
+
+  for (var i = 0; i < result.length; i++) {
+    assertEquals(x + i + 0.5, result[i]);
+  }
+}
+
+f(0, 10);
+f(0, 10);
+%OptimizeFunctionOnNextCall(f);
+f(0, 80000);
diff --git a/test/mjsunit/regress/regress-575364.js b/test/mjsunit/regress/regress-575364.js
index f1dc49e..73136c5 100644
--- a/test/mjsunit/regress/regress-575364.js
+++ b/test/mjsunit/regress/regress-575364.js
@@ -9,4 +9,4 @@
 
 }
 assertFalse(_WASMEXP_ == undefined);
-assertThrows(function() { _WASMEXP_.asmCompileRun(f.toString()); });
+assertThrows(function() { _WASMEXP_.instantiateModuleFromAsm(f.toString()); });
diff --git a/test/mjsunit/regress/regress-crbug-516775.js b/test/mjsunit/regress/regress-crbug-516775.js
index 25d4d01..df190c1 100644
--- a/test/mjsunit/regress/regress-crbug-516775.js
+++ b/test/mjsunit/regress/regress-crbug-516775.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 --harmony-concat-spreadable
+// Flags: --allow-natives-syntax
 
 function arguments_with_length_getter(f) {
   arguments.__defineGetter__('length', f);
diff --git a/test/mjsunit/regress/regress-crbug-577112.js b/test/mjsunit/regress/regress-crbug-577112.js
new file mode 100644
index 0000000..504f921
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-577112.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
+
+Array.prototype.__proto__ = null;
+var prototype = Array.prototype;
+function f() {
+  prototype.lastIndexOf({});
+}
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
diff --git a/test/mjsunit/regress/regress-crbug-580506.js b/test/mjsunit/regress/regress-crbug-580506.js
new file mode 100644
index 0000000..fb03698
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-580506.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
+
+(function() {
+  'use strict';
+  class A extends Function {
+    constructor(...args) {
+      super(...args);
+      this.a = 42;
+    }
+  }
+  var v1 = new A("'use strict';");
+  function f(func) {
+    func.__defineSetter__('a', function() { });
+  }
+  var v2 = new A();
+  f(v2);
+  f(v1);
+})();
diff --git a/test/mjsunit/regress/regress-crbug-580584.js b/test/mjsunit/regress/regress-crbug-580584.js
new file mode 100644
index 0000000..cb6776f
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-580584.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.
+
+function f() { return arguments }
+
+// Reconfiguring function.name should update both the attributes and the value.
+Object.defineProperty(f, "name", {
+  writable: true, configurable: true, value: 10});
+assertEquals({value: 10, writable: true, enumerable: false, configurable: true},
+             Object.getOwnPropertyDescriptor(f, "name"));
+
+var args = f();
+
+// Setting a value for arguments[Symbol.iterator] should not affect the
+// attributes.
+args[Symbol.iterator] = 10;
+assertEquals({value: 10, writable: true, configurable: true, enumerable: false},
+             Object.getOwnPropertyDescriptor(args, Symbol.iterator));
diff --git a/test/mjsunit/regress/regress-crbug-581577.js b/test/mjsunit/regress/regress-crbug-581577.js
new file mode 100644
index 0000000..d95ada5
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-581577.js
@@ -0,0 +1,5 @@
+// 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("", RegExp.prototype.flags);
diff --git a/test/mjsunit/regress/regress-crbug-582051.js b/test/mjsunit/regress/regress-crbug-582051.js
new file mode 100644
index 0000000..93f4e70
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-582051.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
+
+var test_y = false;
+
+function foo(a = 1) {
+  var x = 2;
+  debugger;
+  eval("var y = 3");
+  test_y = true;
+  debugger;
+}
+
+var exception = null;
+var break_count = 0;
+var Debug = debug.Debug;
+var ScopeType = debug.ScopeType;
+
+function listener(event, exec_state) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var scopes = exec_state.frame(0).allScopes();
+    var expectation = [ ScopeType.Block,
+                        ScopeType.Local,
+                        ScopeType.Script,
+                        ScopeType.Global ];
+    assertEquals(expectation, scopes.map(x => x.scopeType()));
+    assertEquals(2, scopes[0].scopeObject().value().x);
+    if (test_y) assertEquals(3, scopes[0].scopeObject().value().y);
+    assertEquals(1, scopes[1].scopeObject().value().a);
+    break_count++;
+  } catch (e) {
+    print(e);
+    exception = e;
+  }
+}
+Debug.setListener(listener);
+foo();
+
+assertNull(exception);
+assertEquals(2, break_count);
diff --git a/test/mjsunit/regress/regress-crbug-582703.js b/test/mjsunit/regress/regress-crbug-582703.js
new file mode 100644
index 0000000..792266f
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-582703.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: --allow-natives-syntax
+
+%FunctionGetScript({});
+%FunctionGetSourceCode({});
diff --git a/test/mjsunit/regress/regress-crbug-583257.js b/test/mjsunit/regress/regress-crbug-583257.js
new file mode 100644
index 0000000..85a08c7
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-583257.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.
+
+Object.defineProperty(String.prototype, "0", { __v_1: 1});
+Object.defineProperty(String.prototype, "3", { __v_1: 1});
+
+(function () {
+  var s = new String();
+  function set(object, index, value) { object[index] = value; }
+  set(s, 10, "value");
+  set(s, 1073741823, "value");
+})();
+
+function __f_11() {
+  Object.preventExtensions(new String());
+}
+__f_11();
+__f_11();
+
+(function() {
+  var i = 10;
+  var a = new String("foo");
+  for (var j = 0; j < i; j++) {
+    a[j] = {};
+  }
+})();
diff --git a/test/mjsunit/regress/regress-crbug-584188.js b/test/mjsunit/regress/regress-crbug-584188.js
new file mode 100644
index 0000000..f54e559
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-584188.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 x = {};
+try {
+Object.defineProperty(String.prototype, "3", { x: function() { x = v; }});
+string = "bla";
+} catch(e) {; }
+assertThrows("Array.prototype.sort.call(string);", TypeError);
diff --git a/test/mjsunit/regress/regress-crbug-589792.js b/test/mjsunit/regress/regress-crbug-589792.js
new file mode 100644
index 0000000..f735afc
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-589792.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: --allow-natives-syntax
+
+var boom = (function(stdlib, foreign, heap) {
+  "use asm";
+  var MEM8 = new stdlib.Uint8Array(heap);
+  var MEM32 = new stdlib.Int32Array(heap);
+  function foo(i, j) {
+    j = MEM8[256];
+    // This following value '10' determines the value of 'rax'
+    MEM32[j >> 10] = 0xabcdefaa;
+    return MEM32[j >> 2] + j
+  }
+  return foo
+})(this, 0, new ArrayBuffer(256));
+%OptimizeFunctionOnNextCall(boom);
+boom(0, 0x1000);
diff --git a/test/mjsunit/regress/regress-crbug-590989-1.js b/test/mjsunit/regress/regress-crbug-590989-1.js
new file mode 100644
index 0000000..73118eb
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-590989-1.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 o = {}
+var p = {foo: 1.5}
+
+function g(x) { return x.foo === +x.foo; }
+
+assertEquals(false, g(o));
+assertEquals(false, g(o));
+%OptimizeFunctionOnNextCall(g);
+assertEquals(false, g(o));  // Still fine here.
+assertEquals(true, g(p));
+%OptimizeFunctionOnNextCall(g);
+assertEquals(false, g(o));  // Confused by type feedback.
diff --git a/test/mjsunit/regress/regress-crbug-590989-2.js b/test/mjsunit/regress/regress-crbug-590989-2.js
new file mode 100644
index 0000000..cae1d9d
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-590989-2.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(x) { return x === +x; }
+
+assertEquals(false, f(undefined));
+assertEquals(false, f(undefined));
+%OptimizeFunctionOnNextCall(f);
+assertEquals(false, f(undefined));  // Interestingly this fails right away.
diff --git a/test/mjsunit/regress/regress-crbug-592343.js b/test/mjsunit/regress/regress-crbug-592343.js
new file mode 100644
index 0000000..c98e921
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-592343.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.
+
+var r = /[^\u{1}-\u{1000}\u{1002}-\u{2000}]/u;
+assertTrue(r.test("\u{0}"));
+assertFalse(r.test("\u{1}"));
+assertFalse(r.test("\u{1000}"));
+assertTrue(r.test("\u{1001}"));
+assertFalse(r.test("\u{1002}"));
+assertFalse(r.test("\u{2000}"));
+assertTrue(r.test("\u{2001}"));
diff --git a/test/mjsunit/regress/regress-crbug-593282.js b/test/mjsunit/regress/regress-crbug-593282.js
new file mode 100644
index 0000000..85c4e10
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-593282.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.
+
+// Flags: --expose-gc --stack-size=120
+
+var __v_11 = {};
+function __f_2(depth) {
+  try {
+    __f_5(depth, __v_11);
+    return true;
+  } catch (e) {
+    gc();
+  }
+}
+function __f_5(n, __v_4) {
+  if (--n == 0) {
+    __f_1(__v_4);
+    return;
+  }
+  __f_5(n, __v_4);
+}
+function __f_1(__v_4) {
+  var __v_5 = new RegExp(__v_4);
+}
+function __f_4() {
+  var __v_1 = 100;
+  var __v_8 = 100000;
+  while (__v_1 < __v_8 - 1) {
+    var __v_3 = Math.floor((__v_1 + __v_8) / 2);
+    if (__f_2(__v_3)) {
+      __v_1 = __v_3;
+    } else {
+      __v_8 = __v_3;
+    }
+  }
+}
+__f_4();
diff --git a/test/mjsunit/regress/regress-crbug-594183.js b/test/mjsunit/regress/regress-crbug-594183.js
new file mode 100644
index 0000000..c87e325
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-594183.js
@@ -0,0 +1,82 @@
+// Copyright 2016 the V8 project 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 global = {}
+
+var fish = [
+  {'name': 'foo'},
+  {'name': 'bar'},
+];
+
+for (var i = 0; i < fish.length; i++) {
+  global[fish[i].name] = 1;
+}
+
+function load() {
+  var sum = 0;
+  for (var i = 0; i < fish.length; i++) {
+    var name = fish[i].name;
+    sum += global[name];
+  }
+  return sum;
+}
+
+load();
+load();
+%OptimizeFunctionOnNextCall(load);
+load();
+assertOptimized(load);
+
+function store() {
+  for (var i = 0; i < fish.length; i++) {
+    var name = fish[i].name;
+    global[name] = 1;
+  }
+}
+
+store();
+store();
+%OptimizeFunctionOnNextCall(store);
+store();
+assertOptimized(store);
+
+// Regression test for KeyedStoreIC bug: would use PROPERTY mode erroneously.
+
+function store_element(obj, key) {
+  obj[key] = 0;
+}
+
+var o1 = new Array(3);
+var o2 = new Array(3);
+o2.o2 = "o2";
+var o3 = new Array(3);
+o3.o3 = "o3";
+var o4 = new Array(3);
+o4.o4 = "o4";
+var o5 = new Array(3);
+o5.o5 = "o5";
+// Make the KeyedStoreIC megamorphic.
+store_element(o1, 0);  // Premonomorphic
+store_element(o1, 0);  // Monomorphic
+store_element(o2, 0);  // 2-way polymorphic.
+store_element(o3, 0);  // 3-way polymorphic.
+store_element(o4, 0);  // 4-way polymorphic.
+store_element(o5, 0);  // Megamorphic.
+
+function inferrable_store(key) {
+  store_element(o5, key);
+}
+
+inferrable_store(0);
+inferrable_store(0);
+%OptimizeFunctionOnNextCall(inferrable_store);
+inferrable_store(0);
+assertOptimized(inferrable_store);
+// If |inferrable_store| emitted a generic keyed store, it won't deopt upon
+// seeing a property name key. It should have inferred a receiver map and
+// emitted an elements store, however.
+inferrable_store("deopt");
+assertUnoptimized(inferrable_store);
diff --git a/test/mjsunit/regress/regress-crbug-594574-concat-leak-1.js b/test/mjsunit/regress/regress-crbug-594574-concat-leak-1.js
new file mode 100644
index 0000000..d5f51a4
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-594574-concat-leak-1.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-gc
+
+array = new Array(10);
+array[0] = 0.1;
+// array[1] = THE_HOLE, reading through the prototype chain
+array[2] = 2.1;
+array[3] = 3.1;
+
+var copy = array.slice(0, array.length);
+
+// Change the array's prototype.
+var proto = {};
+array.__proto__ = proto;
+
+// Define [1] on the prototype to alter the array during concatenation.
+Object.defineProperty(
+  proto, 1, {
+    get() {
+      // Alter the array.
+      array.length = 1;
+      // Force gc to move the array.
+      gc();
+      return "value from proto";
+    },
+    set(new_value) { }
+});
+
+var concatted_array = Array.prototype.concat.call(array);
+assertEquals(concatted_array[0], 0.1);
+assertEquals(concatted_array[1], "value from proto");
+assertEquals(concatted_array[2], undefined);
+assertEquals(concatted_array[3], undefined);
diff --git a/test/mjsunit/regress/regress-crbug-594574-concat-leak-2.js b/test/mjsunit/regress/regress-crbug-594574-concat-leak-2.js
new file mode 100644
index 0000000..f359cfd
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-594574-concat-leak-2.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
+
+array = new Array(10);
+array[0] = 0.1;
+// array[1] = THE_HOLE, reading through the prototype chain
+array[2] = 2.1;
+array[3] = 3.1;
+
+var copy = array.slice(0, array.length);
+
+// Use the defaul array prototype.
+var proto = array.__proto__;
+
+// Define [1] on the prototype to alter the array during concatenation.
+Object.defineProperty(
+  proto, 1, {
+    get() {
+      // Alter the array.
+      array.length = 1;
+      // Force gc to move the array.
+      gc();
+      return "value from proto";
+    },
+    set(new_value) { }
+});
+
+var concatted_array = Array.prototype.concat.call(array);
+assertEquals(concatted_array[0], 0.1);
+assertEquals(concatted_array[1], "value from proto");
+assertEquals(concatted_array[2], undefined);
+assertEquals(concatted_array[3], undefined);
diff --git a/test/mjsunit/regress/regress-crbug-595657.js b/test/mjsunit/regress/regress-crbug-595657.js
new file mode 100644
index 0000000..6532597
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-595657.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: --stack-size=100
+
+function test() {
+  try {
+    test();
+  } catch(e) {
+    /(\2)(a)/.test("");
+  }
+}
+
+test();
diff --git a/test/mjsunit/regress/regress-crbug-599003.js b/test/mjsunit/regress/regress-crbug-599003.js
new file mode 100644
index 0000000..da29455
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-599003.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: --allow-natives-syntax --expose-gc --verify-heap
+
+function A() {}
+
+function g1() {
+  var obj = new A();
+  obj.v0 = 0;
+  obj.v1 = 0;
+  obj.v2 = 0;
+  obj.v3 = 0;
+  obj.v4 = 0;
+  obj.v5 = 0;
+  obj.v6 = 0;
+  obj.v7 = 0;
+  obj.v8 = 0;
+  obj.v9 = 0;
+  return obj;
+}
+
+function g2() {
+  return new A();
+}
+
+var o = g1();
+%OptimizeFunctionOnNextCall(g2);
+g2();
+o = null;
+gc();
+
+for (var i = 0; i < 20; i++) {
+  var o = new A();
+}
+g2();
+
+gc();  // Boom!
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-integer-indexed-element.js b/test/mjsunit/regress/regress-integer-indexed-element.js
new file mode 100644
index 0000000..1bae2d0
--- /dev/null
+++ b/test/mjsunit/regress/regress-integer-indexed-element.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.
+
+var o = {__proto__:new Int32Array(100)};
+Object.prototype[1.3] = 10;
+assertEquals(undefined, o[1.3]);
+
+var o = new Int32Array(100);
+var o2 = new Int32Array(200);
+o.__proto__ = o2;
+assertEquals(undefined, Reflect.get(o, 1.3, o2));
diff --git a/test/mjsunit/regress/regress-seqstrsetchar-ex1.js b/test/mjsunit/regress/regress-seqstrsetchar-ex1.js
index 1fd8d81..444fe4b 100644
--- a/test/mjsunit/regress/regress-seqstrsetchar-ex1.js
+++ b/test/mjsunit/regress/regress-seqstrsetchar-ex1.js
@@ -35,18 +35,18 @@
 // Reduced version of String.fromCharCode;
 // does not actually do the same calculation but exhibits untagging bug.
 function StringFromCharCode(code) {
-  var n = %_ArgumentsLength();
+  var n = arguments.length;
   var one_byte = %NewString(n, true);
   var i;
   for (i = 0; i < n; i++) {
-    var code = %_Arguments(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);
+    var code = arguments[i];
     %_TwoByteSeqStringSetChar(j, code, two_byte);
   }
   return one_byte + two_byte;
diff --git a/test/mjsunit/regress/regress-v8-4839.js b/test/mjsunit/regress/regress-v8-4839.js
new file mode 100644
index 0000000..120685b
--- /dev/null
+++ b/test/mjsunit/regress/regress-v8-4839.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: --allow-natives-syntax
+
+function dummy() { }
+
+(function InlinedFunctionTestContext() {
+  var f = function() { }
+
+  function g() {
+   var s = "hey";
+   dummy();  // Force a deopt point.
+   if (f()) return s;
+  }
+
+  g();
+  g();
+  g();
+  %OptimizeFunctionOnNextCall(g);
+  f = function() { return true; }
+  assertEquals("hey", g());
+})();
+
+(function InlinedConstructorReturnTestContext() {
+  function c() { return 1; }
+
+  var f = function() { return !(new c());  }
+
+  function g() {
+   var s = "hey";
+   dummy();  // Force a deopt point.
+   if (f()) return s;
+  }
+
+  g();
+  g();
+  g();
+  %OptimizeFunctionOnNextCall(g);
+  f = function() { return true; }
+  assertEquals("hey", g());
+})();
+
+(function InlinedConstructorNoReturnTestContext() {
+  function c() { }
+
+  var f = function() { return !(new c());  }
+
+  function g() {
+   var s = "hey";
+   dummy();  // Force a deopt point.
+   if (f()) return s;
+  }
+
+  g();
+  g();
+  g();
+  %OptimizeFunctionOnNextCall(g);
+  f = function() { return true; }
+  assertEquals("hey", g());
+})();
diff --git a/test/mjsunit/regress/regress-v8-4972.js b/test/mjsunit/regress/regress-v8-4972.js
new file mode 100644
index 0000000..689ae03
--- /dev/null
+++ b/test/mjsunit/regress/regress-v8-4972.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.
+
+new class extends new Proxy(class {},{}) {}
diff --git a/test/mjsunit/samevalue.js b/test/mjsunit/samevalue.js
index 038fd68..356e888 100644
--- a/test/mjsunit/samevalue.js
+++ b/test/mjsunit/samevalue.js
@@ -26,14 +26,14 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-// Flags: --expose-natives-as natives
+// Flags: --expose-natives-as natives --allow-natives-syntax
 // Test the SameValue and SameValueZero internal methods.
 
 var obj1 = {x: 10, y: 11, z: "test"};
 var obj2 = {x: 10, y: 11, z: "test"};
 
 var sameValue = Object.is;
-var sameValueZero = natives.ImportNow("SameValueZero");
+var sameValueZero = function(x, y) { return %SameValueZero(x, y); }
 
 // Calls SameValue and SameValueZero and checks that their results match.
 function sameValueBoth(a, b) {
diff --git a/test/mjsunit/strict-mode.js b/test/mjsunit/strict-mode.js
index 6beb9c6..63dc9d0 100644
--- a/test/mjsunit/strict-mode.js
+++ b/test/mjsunit/strict-mode.js
@@ -1149,7 +1149,9 @@
 
   function strict() {
     "use strict";
-    return return_my_caller();
+    // Returning result via local variable to avoid tail call optimization.
+    var res = return_my_caller();
+    return res;
   }
   assertSame(null, strict());
 
@@ -1163,7 +1165,9 @@
 (function TestNonStrictFunctionCallerPill() {
   function strict(n) {
     "use strict";
-    return non_strict(n);
+    // Returning result via local variable to avoid tail call optimization.
+    var res = non_strict(n);
+    return res;
   }
 
   function recurse(n, then) {
@@ -1191,7 +1195,9 @@
 (function TestNonStrictFunctionCallerDescriptorPill() {
   function strict(n) {
     "use strict";
-    return non_strict(n);
+    // Returning result via local variable to avoid tail call optimization.
+    var res = non_strict(n);
+    return res;
   }
 
   function recurse(n, then) {
diff --git a/test/mjsunit/strong/declaration-after-use.js b/test/mjsunit/strong/declaration-after-use.js
deleted file mode 100644
index 3530105..0000000
--- a/test/mjsunit/strong/declaration-after-use.js
+++ /dev/null
@@ -1,255 +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: --strong-mode
-
-// Note that it's essential for these tests that the reference is inside dead
-// code (because we already produce ReferenceErrors for run-time unresolved
-// variables and don't want to confuse those with strong mode errors). But the
-// errors should *not* be inside lazy, unexecuted functions, since lazy parsing
-// doesn't produce strong mode scoping errors).
-
-// In addition, assertThrows will call eval and that changes variable binding
-// types (see e.g., UNBOUND_EVAL_SHADOWED). We can avoid unwanted side effects
-// by wrapping the code to be tested inside an outer function.
-function assertThrowsHelper(code) {
-  "use strict";
-  let prologue = "(function outer() { if (false) { ";
-  let epilogue = " } })();";
-
-  assertThrows("'use strong'; " + prologue + code + epilogue, ReferenceError);
-
-  // Make sure the error happens only in strong mode (note that we need strict
-  // mode here because of let).
-  assertDoesNotThrow("'use strict'; " + prologue + code + epilogue);
-}
-
-(function DeclarationAfterUse() {
-  // Note that these tests only test cases where the declaration is found but is
-  // after the use. In particular, we cannot yet detect cases where the use can
-  // possibly bind to a global variable.
-  assertThrowsHelper("x; let x = 0;");
-  assertThrowsHelper("function f() { x; let x = 0; }");
-  assertThrowsHelper("function f() { x; } let x = 0;");
-
-  assertThrowsHelper("x; const x = 0;");
-  assertThrowsHelper("function f() { x; const x = 0; }");
-  assertThrowsHelper("function f() { x; } const x = 0;");
-
-  // These tests needs to be done a bit more manually, since var is not allowed
-  // in strong mode:
-  assertThrows(
-      `(function outer() {
-        function f() { 'use strong'; if (false) { x; } } var x = 0; f();
-      })()`,
-      ReferenceError);
-  assertDoesNotThrow(
-      "(function outer() {\n" +
-      "  function f() { if (false) { x; } } var x = 0; f(); \n" +
-      "})()");
-
-  assertThrows(
-      "(function outer() {\n" +
-      "  function f() { 'use strong'; if (false) { x; } } var x; f(); \n" +
-      "})()",
-      ReferenceError);
-  assertDoesNotThrow(
-      "(function outer() {\n" +
-      "  function f() { if (false) { x; } } var x; f(); \n" +
-      "})()");
-
-  // Use occurring in the initializer of the declaration:
-  assertThrowsHelper("let x = x + 1;");
-  assertThrowsHelper("let x = x;");
-  assertThrowsHelper("let x = y, y = 4;");
-  assertThrowsHelper("let x = function() { x; }");
-  assertThrowsHelper("let x = a => { x; }");
-  assertThrowsHelper("function f(x) { return x; }; let x = f(x);");
-  assertThrowsHelper("const x = x;");
-  assertThrowsHelper("const x = function() { x; }");
-  assertThrowsHelper("const x = a => { x; }");
-  assertThrowsHelper("function f(x) {return x}; const x = f(x);");
-
-  assertThrowsHelper("for (let x = x; ; ) { }");
-  assertThrowsHelper("for (const x = x; ; ) { }");
-  assertThrowsHelper("for (let x = y, y; ; ) { }");
-  assertThrowsHelper("for (const x = y, y = 0; ; ) { }");
-
-  // Computed property names
-  assertThrowsHelper("let o = { 'a': 'b', [o.a]: 'c'};");
-})();
-
-
-(function DeclarationAfterUseInClasses() {
-  // Referring to a variable declared later
-  assertThrowsHelper("class C { m() { x; } } let x = 0;");
-  assertThrowsHelper("class C { static m() { x; } } let x = 0;");
-  assertThrowsHelper("class C { [x]() { } } let x = 0;");
-
-  assertThrowsHelper("class C { m() { x; } } const x = 0;");
-  assertThrowsHelper("class C { static m() { x; } } const x = 0;");
-  assertThrowsHelper("class C { [x]() { } } const x = 0;");
-
-  // Referring to the class name.
-  assertThrowsHelper("class C extends C { }");
-  assertThrowsHelper("let C = class C2 extends C { }");
-  assertThrowsHelper("let C = class C2 extends C2 { }");
-
-  assertThrowsHelper("let C = class C2 { constructor() { C; } }");
-  assertThrowsHelper("let C = class C2 { method() { C; } }");
-  assertThrowsHelper("let C = class C2 { *generator_method() { C; } }");
-
-  assertThrowsHelper(
-      `let C = class C2 {
-        static a() { return 'A'; }
-        [C.a()]() { return 'B'; }
-      };`);
-
-  assertThrowsHelper(
-      `let C = class C2 {
-        static a() { return 'A'; }
-        [C2.a()]() { return 'B'; }
-      };`);
-
-  assertThrowsHelper(
-      `let C = class C2 {
-        [(function() { C; return 'A';})()]() { return 'B'; }
-      };`);
-
-  // The reference to C or C2 is inside a function, but not a method.
-  assertThrowsHelper(
-      `let C = class C2 {
-        [(function() { C2; return 'A';})()]() { return 'B'; }
-      };`);
-
-  assertThrowsHelper(
-      `let C = class C2 {
-        [(function() { C; return 'A';})()]() { return 'B'; }
-      };`);
-
-  // The reference to C or C2 is inside a method, but it's not a method of the
-  // relevant class (C2).
-  assertThrowsHelper(
-      `let C = class C2 {
-        [(new (class D { m() { C2; return 'A'; } })).m()]() {
-          return 'B';
-        }
-      }`);
-
-  assertThrowsHelper(
-      `let C = class C2 {
-        [(new (class D { m() { C; return 'A'; } })).m()]() {
-          return 'B';
-        }
-      }`);
-
-  assertThrowsHelper(
-      `let C = class C2 {
-        [({m() { C2; return 'A'; }}).m()]() { return 'B'; }
-      }`);
-
-  assertThrowsHelper(
-      `let C = class C2 {
-        [({m() { C; return 'A'; }}).m()]() { return 'B'; }
-      }`);
-
-  assertThrowsHelper(
-      `class COuter {
-        m() {
-          class CInner {
-            [({ m() { CInner; return 'A'; } }).m()]() {
-                return 'B';
-            }
-          }
-        }
-      }`);
-})();
-
-
-(function UsesWhichAreFine() {
-  "use strong";
-
-  let var1 = 0;
-  var1;
-
-  let var2a = 0, var2b = var2a + 1, var2c = 2 + var2b;
-
-  for (let var3 = 0; var3 < 1; var3++) {
-    var3;
-  }
-
-  for (let var4a = 0, var4b = var4a; var4a + var4b < 4; var4a++, var4b++) {
-    var4a;
-    var4b;
-  }
-
-  let var5 = 5;
-  for (; var5 < 10; ++var5) { }
-
-  let arr = [1, 2];
-  for (let i of arr) {
-    i;
-  }
-
-  try {
-    throw "error";
-  } catch (e) {
-    e;
-  }
-
-  function func1() { func1; this; }
-  func1();
-  func1;
-
-  function * func2() { func2; this; }
-  func2();
-  func2;
-
-  function func4(p, ...rest) { p; rest; this; func2; }
-  // TODO(arv): The arity checking is not correct with rest parameters.
-  func4(1, 2);
-
-  let func5 = (p1, p2) => { p1; p2; };
-  func5(1, 2);
-
-  let func5b = p1 => p1;
-  func5b(1);
-
-  function func6() {
-    var1, var2a, var2b, var2c;
-  }
-
-  class C1 { constructor() { C1; } }; new C1();
-  let C2 = class C3 { constructor() { C3; } }; new C2();
-
-  class C4 { method() { C4; } *generator_method() { C4; } }; new C4();
-  let C5 = class C6 { method() { C6; } *generator_method() { C6; } }; new C5();
-
-  class C7 { static method() { C7; } }; new C7();
-  let C8 = class C9 { static method() { C9; } }; new C8();
-
-  class C10 { get x() { C10; } }; new C10();
-  let C11 = class C12 { get x() { C12; } }; new C11();
-
-  // Regression test for unnamed classes.
-  let C13 = class { m() { var1; } };
-
-  class COuter {
-    m() {
-      class CInner {
-        // Here we can refer to COuter but not to CInner (see corresponding
-        // assertion test):
-        [({ m() { COuter; return 'A'; } }).m()]() { return 'B'; }
-        // And here we can refer to both:
-        n() { COuter; CInner; }
-      }
-      return new CInner();
-    }
-  }
-  (new COuter()).m().n();
-
-  // Making sure the check which is supposed to prevent "object literal inside
-  // computed property name references the class name" is not too generic:
-  class C14 { m() { let obj = { n() { C14 } }; obj.n(); } }; (new C14()).m();
-})();
diff --git a/test/mjsunit/strong/for-in.js b/test/mjsunit/strong/for-in.js
index 8fa9010..641248c 100644
--- a/test/mjsunit/strong/for-in.js
+++ b/test/mjsunit/strong/for-in.js
@@ -9,9 +9,3 @@
   assertThrows("'use strong'; for (let x in []) {}", SyntaxError);
   assertThrows("'use strong'; for (const x in []) {}", SyntaxError);
 })();
-
-(function ForOfStatement() {
-  assertTrue(eval("'use strong'; for (x of []) {} true"));
-  assertTrue(eval("'use strong'; for (let x of []) {} true"));
-  assertTrue(eval("'use strong'; for (const x of []) {} true"));
-})();
diff --git a/test/mjsunit/strong/mutually-recursive-classes.js b/test/mjsunit/strong/mutually-recursive-classes.js
deleted file mode 100644
index 204c396..0000000
--- a/test/mjsunit/strong/mutually-recursive-classes.js
+++ /dev/null
@@ -1,229 +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: --strong-mode
-"use strict"
-
-let prologue_dead = "(function outer() { if (false) { ";
-let epilogue_dead = " } })();";
-
-let prologue_live = "(function outer() { ";
-let epilogue_live = "})();";
-
-// For code which already throws a run-time error in non-strong mode; we assert
-// that we now get the error already compilation time.
-function assertLateErrorsBecomeEarly(code) {
-  assertThrows("'use strong'; " + prologue_dead + code + epilogue_dead,
-               ReferenceError);
-
-  // Make sure the error happens only in strong mode (note that we need strict
-  // mode here because of let).
-  assertDoesNotThrow("'use strict'; " + prologue_dead + code + epilogue_dead);
-
-  // But if we don't put the references inside a dead code, it throws a run-time
-  // error (also in strict mode).
-  assertThrows("'use strong'; " + prologue_live + code + epilogue_live,
-               ReferenceError);
-  assertThrows("'use strict'; " + prologue_live + code + epilogue_live,
-               ReferenceError);
-}
-
-// For code which doesn't throw an error at all in non-strong mode.
-function assertNonErrorsBecomeEarly(code) {
-  assertThrows("'use strong'; " + prologue_dead + code + epilogue_dead,
-               ReferenceError);
-  assertDoesNotThrow("'use strict'; " + prologue_dead + code + epilogue_dead);
-
-  assertThrows("'use strong'; " + prologue_live + code + epilogue_live,
-               ReferenceError);
-  assertDoesNotThrow("'use strict'; " + prologue_live + code + epilogue_live,
-                     ReferenceError);
-}
-
-(function InitTimeReferenceForward() {
-  // It's never OK to have an init time reference to a class which hasn't been
-  // declared.
-  assertLateErrorsBecomeEarly(
-      `class A extends B { }
-      class B {}`);
-
-  assertLateErrorsBecomeEarly(
-      `class A {
-        [B.sm()]() { }
-      }
-      class B {
-        static sm() { return 0; }
-      }`);
-})();
-
-(function InitTimeReferenceBackward() {
-  // Backwards is of course fine.
-  "use strong";
-  class A {
-    static sm() { return 0; }
-  }
-  let i = "making these classes non-consecutive";
-  class B extends A {};
-  "by inserting statements and declarations in between";
-  class C {
-    [A.sm()]() { }
-  };
-})();
-
-(function BasicMutualRecursion() {
-  "use strong";
-  class A {
-    m() { B; }
-    static sm() { B; }
-  }
-  // No statements or declarations between the classes.
-  class B {
-    m() { A; }
-    static sm() { A; }
-  }
-})();
-
-(function MutualRecursionWithMoreClasses() {
-  "use strong";
-  class A {
-    m() { B; C; }
-    static sm() { B; C; }
-  }
-  class B {
-    m() { A; C; }
-    static sm() { A; C; }
-  }
-  class C {
-    m() { A; B; }
-    static sm() { A; B; }
-  }
-})();
-
-(function ReferringForwardInDeeperScopes() {
-  "use strong";
-
-  function foo() {
-    class A1 {
-      m() { B1; }
-    }
-    class B1 { }
-  }
-
-  class Outer {
-    m() {
-      class A2 {
-        m() { B2; }
-      }
-      class B2 { }
-    }
-  }
-
-  for (let i = 0; i < 1; ++i) {
-    class A3 {
-      m() { B3; }
-    }
-    class B3 { }
-  }
-
-  (a, b) => {
-    class A4 {
-      m() { B4; }
-    }
-    class B4 { }
-  }
-})();
-
-(function ReferringForwardButClassesNotConsecutive() {
-  assertNonErrorsBecomeEarly(
-      `class A {
-        m() { B; }
-      }
-      ;
-      class B {}`);
-
-  assertNonErrorsBecomeEarly(
-      `let A = class {
-        m() { B; }
-      }
-      class B {}`);
-
-  assertNonErrorsBecomeEarly(
-      `class A {
-        m() { B1; } // Just a normal use-before-declaration.
-      }
-      let B1 = class B2 {}`);
-
-  assertNonErrorsBecomeEarly(
-      `class A {
-        m() { B; }
-      }
-      let i = 0;
-      class B {}`);
-
-  assertNonErrorsBecomeEarly(
-      `class A {
-        m() { B; }
-      }
-      function foo() {}
-      class B {}`);
-
-  assertNonErrorsBecomeEarly(
-      `function foo() {
-        class A {
-          m() { B; }
-        }
-      }
-      class B {}`);
-
-  assertNonErrorsBecomeEarly(
-      `class A extends class B { m() { C; } } {
-      }
-      class C { }`);
-
-  assertLateErrorsBecomeEarly(
-      `class A extends class B { [C.sm()]() { } } {
-      }
-      class C { static sm() { return 'a';} }`);
-
-  assertLateErrorsBecomeEarly(
-      `class A extends class B extends C { } {
-      }
-      class C { }`);
-})();
-
-
-(function RegressionForClassResolution() {
-  assertNonErrorsBecomeEarly(
-      `let A = class B {
-        m() { C; }
-      }
-      ;;;;
-      class C {}
-      class B {}`);
-})();
-
-
-(function TestMultipleMethodScopes() {
-  "use strong";
-
-  // Test cases where the reference is inside multiple method scopes.
-  class A1 {
-    m() {
-      class C1 {
-        m() { B1; }
-      }
-    }
-  }
-  class B1 { }
-
-  ;
-
-  class A2 {
-    m() {
-      class C2 extends B2 {
-      }
-    }
-  }
-  class B2 { }
-})();
diff --git a/test/mjsunit/to_number_order.js b/test/mjsunit/to_number_order.js
index 50e4bc7..c20ec5e 100644
--- a/test/mjsunit/to_number_order.js
+++ b/test/mjsunit/to_number_order.js
@@ -56,6 +56,13 @@
 assertEquals(1, Math.pow(v, w));
 assertEquals("hestfisk", x, "pow");
 
+x = "";
+var a = {valueOf: function() { x += "hest"; return 1/0; }};
+var b = {valueOf: function() { x += "fisk"; return 1}};
+assertEquals(1/0, Math.hypot(a, b));
+assertEquals("hestfisk", x, "hypot");
+
+
 var year = { valueOf: function() { x += 1; return 2007; } };
 var month = { valueOf: function() { x += 2; return 2; } };
 var date = { valueOf: function() { x += 3; return 4; } };
diff --git a/test/mjsunit/typeof.js b/test/mjsunit/typeof.js
index 8aa0ab1..864f1cf 100644
--- a/test/mjsunit/typeof.js
+++ b/test/mjsunit/typeof.js
@@ -35,3 +35,5 @@
 
 function test(x, y) { return x == y; }
 assertTrue(test('object', typeof r));
+
+assertFalse(typeof null == "undefined");
diff --git a/test/mjsunit/undetectable-compare.js b/test/mjsunit/undetectable-compare.js
index fbfbbe1..3b97f5e 100644
--- a/test/mjsunit/undetectable-compare.js
+++ b/test/mjsunit/undetectable-compare.js
@@ -92,5 +92,4 @@
 }
 
 
-assertFalse(undetectable == %GetUndetectable());
 assertFalse(undetectable === %GetUndetectable());
diff --git a/test/mjsunit/wasm/asm-wasm.js b/test/mjsunit/wasm/asm-wasm.js
index 8dfe85a..3f936f5 100644
--- a/test/mjsunit/wasm/asm-wasm.js
+++ b/test/mjsunit/wasm/asm-wasm.js
@@ -15,7 +15,9 @@
   return {caller: caller};
 }
 
-assertEquals(11, _WASMEXP_.asmCompileRun(EmptyTest.toString()));
+assertEquals(11, _WASMEXP_.instantiateModuleFromAsm(
+      EmptyTest.toString()).caller());
+
 
 function IntTest() {
   "use asm";
@@ -24,7 +26,7 @@
     b = b|0;
     var c = (b + 1)|0
     var d = 3.0;
-    var e = d | 0;  // double conversion
+    var e = ~~d;  // double conversion
     return (a + c + 1)|0;
   }
 
@@ -35,7 +37,9 @@
   return {caller: caller};
 }
 
-assertEquals(101, _WASMEXP_.asmCompileRun(IntTest.toString()));
+assertEquals(101, _WASMEXP_.instantiateModuleFromAsm(
+      IntTest.toString()).caller());
+
 
 function Float64Test() {
   "use asm";
@@ -59,7 +63,9 @@
   return {caller: caller};
 }
 
-assertEquals(1, _WASMEXP_.asmCompileRun(Float64Test.toString()));
+assertEquals(1, _WASMEXP_.instantiateModuleFromAsm(
+      Float64Test.toString()).caller());
+
 
 function BadModule() {
   "use asm";
@@ -78,9 +84,10 @@
 }
 
 assertThrows(function() {
-  _WASMEXP_.asmCompileRun(BadModule.toString())
+  _WASMEXP_.instantiateModuleFromAsm(BadModule.toString()).caller();
 });
 
+
 function TestReturnInBlock() {
   "use asm";
 
@@ -98,7 +105,9 @@
   return {caller: caller};
 }
 
-assertEquals(1, _WASMEXP_.asmCompileRun(TestReturnInBlock.toString()));
+assertEquals(1, _WASMEXP_.instantiateModuleFromAsm(
+      TestReturnInBlock.toString()).caller());
+
 
 function TestWhileSimple() {
   "use asm";
@@ -114,7 +123,9 @@
   return {caller: caller};
 }
 
-assertEquals(5, _WASMEXP_.asmCompileRun(TestWhileSimple.toString()));
+assertEquals(5, _WASMEXP_.instantiateModuleFromAsm(
+      TestWhileSimple.toString()).caller());
+
 
 function TestWhileWithoutBraces() {
   "use asm";
@@ -129,7 +140,9 @@
   return {caller: caller};
 }
 
-assertEquals(4, _WASMEXP_.asmCompileRun(TestWhileWithoutBraces.toString()));
+assertEquals(4, _WASMEXP_.instantiateModuleFromAsm(
+      TestWhileWithoutBraces.toString()).caller());
+
 
 function TestReturnInWhile() {
   "use asm";
@@ -146,7 +159,9 @@
   return {caller: caller};
 }
 
-assertEquals(6, _WASMEXP_.asmCompileRun(TestReturnInWhile.toString()));
+assertEquals(6, _WASMEXP_.instantiateModuleFromAsm(
+      TestReturnInWhile.toString()).caller());
+
 
 function TestReturnInWhileWithoutBraces() {
   "use asm";
@@ -161,7 +176,10 @@
   return {caller: caller};
 }
 
-assertEquals(7, _WASMEXP_.asmCompileRun(TestReturnInWhileWithoutBraces.toString()));
+assertEquals(
+    7, _WASMEXP_.instantiateModuleFromAsm(
+      TestReturnInWhileWithoutBraces.toString()).caller());
+
 
 function TestBreakInWhile() {
   "use asm";
@@ -176,7 +194,9 @@
   return {caller: caller};
 }
 
-assertEquals(8, _WASMEXP_.asmCompileRun(TestBreakInWhile.toString()));
+assertEquals(8, _WASMEXP_.instantiateModuleFromAsm(
+      TestBreakInWhile.toString()).caller());
+
 
 function TestBreakInNestedWhile() {
   "use asm";
@@ -198,7 +218,9 @@
   return {caller: caller};
 }
 
-assertEquals(9, _WASMEXP_.asmCompileRun(TestBreakInNestedWhile.toString()));
+assertEquals(9, _WASMEXP_.instantiateModuleFromAsm(
+      TestBreakInNestedWhile.toString()).caller());
+
 
 function TestBreakInBlock() {
   "use asm";
@@ -218,7 +240,9 @@
   return {caller: caller};
 }
 
-assertEquals(10, _WASMEXP_.asmCompileRun(TestBreakInBlock.toString()));
+assertEquals(10, _WASMEXP_.instantiateModuleFromAsm(
+      TestBreakInBlock.toString()).caller());
+
 
 function TestBreakInNamedWhile() {
   "use asm";
@@ -237,7 +261,9 @@
   return {caller: caller};
 }
 
-assertEquals(11, _WASMEXP_.asmCompileRun(TestBreakInNamedWhile.toString()));
+assertEquals(11, _WASMEXP_.instantiateModuleFromAsm(
+      TestBreakInNamedWhile.toString()).caller());
+
 
 function TestContinue() {
   "use asm";
@@ -258,7 +284,9 @@
   return {caller: caller};
 }
 
-assertEquals(-5, _WASMEXP_.asmCompileRun(TestContinue.toString()));
+assertEquals(-5, _WASMEXP_.instantiateModuleFromAsm(
+      TestContinue.toString()).caller());
+
 
 function TestContinueInNamedWhile() {
   "use asm";
@@ -284,7 +312,9 @@
   return {caller: caller};
 }
 
-assertEquals(20, _WASMEXP_.asmCompileRun(TestContinueInNamedWhile.toString()));
+assertEquals(20, _WASMEXP_.instantiateModuleFromAsm(
+      TestContinueInNamedWhile.toString()).caller());
+
 
 function TestNot() {
   "use asm";
@@ -297,7 +327,9 @@
   return {caller:caller};
 }
 
-assertEquals(1, _WASMEXP_.asmCompileRun(TestNot.toString()));
+assertEquals(1, _WASMEXP_.instantiateModuleFromAsm(
+      TestNot.toString()).caller());
+
 
 function TestNotEquals() {
   "use asm";
@@ -313,7 +345,9 @@
   return {caller:caller};
 }
 
-assertEquals(21, _WASMEXP_.asmCompileRun(TestNotEquals.toString()));
+assertEquals(21, _WASMEXP_.instantiateModuleFromAsm(
+      TestNotEquals.toString()).caller());
+
 
 function TestUnsignedComparison() {
   "use asm";
@@ -329,7 +363,9 @@
   return {caller:caller};
 }
 
-assertEquals(22, _WASMEXP_.asmCompileRun(TestUnsignedComparison.toString()));
+assertEquals(22, _WASMEXP_.instantiateModuleFromAsm(
+      TestUnsignedComparison.toString()).caller());
+
 
 function TestMixedAdd() {
   "use asm";
@@ -350,7 +386,9 @@
   return {caller:caller};
 }
 
-assertEquals(23, _WASMEXP_.asmCompileRun(TestMixedAdd.toString()));
+assertEquals(23, _WASMEXP_.instantiateModuleFromAsm(
+      TestMixedAdd.toString()).caller());
+
 
 function TestInt32HeapAccess(stdlib, foreign, buffer) {
   "use asm";
@@ -368,27 +406,49 @@
   return {caller: caller};
 }
 
-assertEquals(7, _WASMEXP_.asmCompileRun(TestInt32HeapAccess.toString()));
+assertEquals(7, _WASMEXP_.instantiateModuleFromAsm(
+      TestInt32HeapAccess.toString()).caller());
+
+
+function TestInt32HeapAccessExternal() {
+  var memory = new ArrayBuffer(1024);
+  var memory_int32 = new Int32Array(memory);
+  var module = _WASMEXP_.instantiateModuleFromAsm(
+      TestInt32HeapAccess.toString(), null, memory);
+  module.__init__();
+  assertEquals(7, module.caller());
+  assertEquals(7, memory_int32[2]);
+}
+
+TestInt32HeapAccessExternal();
+
 
 function TestHeapAccessIntTypes() {
   var types = [
-    ['Int8Array', '>> 0'],
-    ['Uint8Array', '>> 0'],
-    ['Int16Array', '>> 1'],
-    ['Uint16Array', '>> 1'],
-    ['Int32Array', '>> 2'],
-    ['Uint32Array', '>> 2'],
+    [Int8Array, 'Int8Array', '>> 0'],
+    [Uint8Array, 'Uint8Array', '>> 0'],
+    [Int16Array, 'Int16Array', '>> 1'],
+    [Uint16Array, 'Uint16Array', '>> 1'],
+    [Int32Array, 'Int32Array', '>> 2'],
+    [Uint32Array, 'Uint32Array', '>> 2'],
   ];
   for (var i = 0; i < types.length; i++) {
     var code = TestInt32HeapAccess.toString();
-    code = code.replace('Int32Array', types[i][0]);
-    code = code.replace(/>> 2/g, types[i][1]);
-    assertEquals(7, _WASMEXP_.asmCompileRun(code));
+    code = code.replace('Int32Array', types[i][1]);
+    code = code.replace(/>> 2/g, types[i][2]);
+    var memory = new ArrayBuffer(1024);
+    var memory_view = new types[i][0](memory);
+    var module = _WASMEXP_.instantiateModuleFromAsm(code, null, memory);
+    module.__init__();
+    assertEquals(7, module.caller());
+    assertEquals(7, memory_view[2]);
+    assertEquals(7, _WASMEXP_.instantiateModuleFromAsm(code).caller());
   }
 }
 
 TestHeapAccessIntTypes();
 
+
 function TestFloatHeapAccess(stdlib, foreign, buffer) {
   "use asm";
 
@@ -411,7 +471,22 @@
   return {caller: caller};
 }
 
-assertEquals(1, _WASMEXP_.asmCompileRun(TestFloatHeapAccess.toString()));
+assertEquals(1, _WASMEXP_.instantiateModuleFromAsm(
+      TestFloatHeapAccess.toString()).caller());
+
+
+function TestFloatHeapAccessExternal() {
+  var memory = new ArrayBuffer(1024);
+  var memory_float64 = new Float64Array(memory);
+  var module = _WASMEXP_.instantiateModuleFromAsm(
+      TestFloatHeapAccess.toString(), null, memory);
+  module.__init__();
+  assertEquals(1, module.caller());
+  assertEquals(9.0, memory_float64[1]);
+}
+
+TestFloatHeapAccessExternal();
+
 
 function TestConvertI32() {
   "use asm";
@@ -427,7 +502,9 @@
   return {caller:caller};
 }
 
-assertEquals(24, _WASMEXP_.asmCompileRun(TestConvertI32.toString()));
+assertEquals(24, _WASMEXP_.instantiateModuleFromAsm(
+      TestConvertI32.toString()).caller());
+
 
 function TestConvertF64FromInt() {
   "use asm";
@@ -443,7 +520,9 @@
   return {caller:caller};
 }
 
-assertEquals(25, _WASMEXP_.asmCompileRun(TestConvertF64FromInt.toString()));
+assertEquals(25, _WASMEXP_.instantiateModuleFromAsm(
+      TestConvertF64FromInt.toString()).caller());
+
 
 function TestConvertF64FromUnsigned() {
   "use asm";
@@ -461,7 +540,9 @@
   return {caller:caller};
 }
 
-assertEquals(26, _WASMEXP_.asmCompileRun(TestConvertF64FromUnsigned.toString()));
+assertEquals(26, _WASMEXP_.instantiateModuleFromAsm(
+      TestConvertF64FromUnsigned.toString()).caller());
+
 
 function TestModInt() {
   "use asm";
@@ -475,7 +556,9 @@
   return {caller:caller};
 }
 
-assertEquals(-27, _WASMEXP_.asmCompileRun(TestModInt.toString()));
+assertEquals(-27, _WASMEXP_.instantiateModuleFromAsm(
+      TestModInt.toString()).caller());
+
 
 function TestModUnsignedInt() {
   "use asm";
@@ -489,7 +572,9 @@
   return {caller:caller};
 }
 
-assertEquals(8, _WASMEXP_.asmCompileRun(TestModUnsignedInt.toString()));
+assertEquals(8, _WASMEXP_.instantiateModuleFromAsm(
+      TestModUnsignedInt.toString()).caller());
+
 
 function TestModDouble() {
   "use asm";
@@ -506,7 +591,9 @@
   return {caller:caller};
 }
 
-assertEquals(28, _WASMEXP_.asmCompileRun(TestModDouble.toString()));
+assertEquals(28, _WASMEXP_.instantiateModuleFromAsm(
+      TestModDouble.toString()).caller());
+
 
 /*
 TODO: Fix parsing of negative doubles
@@ -526,9 +613,11 @@
   return {caller:caller};
 }
 
-assertEquals(28, _WASMEXP_.asmCompileRun(TestModDoubleNegative.toString()));
+assertEquals(28, _WASMEXP_.instantiateModuleFromAsm(
+      TestModDoubleNegative.toString()).caller());
 */
 
+
 function TestNamedFunctions() {
   "use asm";
 
@@ -552,6 +641,7 @@
 module.init();
 assertEquals(77.5, module.add());
 
+
 function TestGlobalsWithInit() {
   "use asm";
 
@@ -569,6 +659,7 @@
 module.__init__();
 assertEquals(77.5, module.add());
 
+
 function TestForLoop() {
   "use asm"
 
@@ -584,7 +675,9 @@
   return {caller:caller};
 }
 
-assertEquals(54, _WASMEXP_.asmCompileRun(TestForLoop.toString()));
+assertEquals(54, _WASMEXP_.instantiateModuleFromAsm(
+      TestForLoop.toString()).caller());
+
 
 function TestForLoopWithoutInit() {
   "use asm"
@@ -601,7 +694,9 @@
   return {caller:caller};
 }
 
-assertEquals(100, _WASMEXP_.asmCompileRun(TestForLoopWithoutInit.toString()));
+assertEquals(100, _WASMEXP_.instantiateModuleFromAsm(
+      TestForLoopWithoutInit.toString()).caller());
+
 
 function TestForLoopWithoutCondition() {
   "use asm"
@@ -621,7 +716,9 @@
   return {caller:caller};
 }
 
-assertEquals(66, _WASMEXP_.asmCompileRun(TestForLoopWithoutCondition.toString()));
+assertEquals(66, _WASMEXP_.instantiateModuleFromAsm(
+      TestForLoopWithoutCondition.toString()).caller());
+
 
 function TestForLoopWithoutNext() {
   "use asm"
@@ -637,7 +734,9 @@
   return {caller:caller};
 }
 
-assertEquals(41, _WASMEXP_.asmCompileRun(TestForLoopWithoutNext.toString()));
+assertEquals(41, _WASMEXP_.instantiateModuleFromAsm(
+      TestForLoopWithoutNext.toString()).caller());
+
 
 function TestForLoopWithoutBody() {
   "use asm"
@@ -652,7 +751,9 @@
   return {caller:caller};
 }
 
-assertEquals(45, _WASMEXP_.asmCompileRun(TestForLoopWithoutBody.toString()));
+assertEquals(45, _WASMEXP_.instantiateModuleFromAsm(
+      TestForLoopWithoutBody.toString()).caller());
+
 
 function TestDoWhile() {
   "use asm"
@@ -670,7 +771,9 @@
   return {caller:caller};
 }
 
-assertEquals(84, _WASMEXP_.asmCompileRun(TestDoWhile.toString()));
+assertEquals(84, _WASMEXP_.instantiateModuleFromAsm(
+      TestDoWhile.toString()).caller());
+
 
 function TestConditional() {
   "use asm"
@@ -683,7 +786,9 @@
   return {caller:caller};
 }
 
-assertEquals(41, _WASMEXP_.asmCompileRun(TestConditional.toString()));
+assertEquals(41, _WASMEXP_.instantiateModuleFromAsm(
+      TestConditional.toString()).caller());
+
 
 function TestSwitch() {
   "use asm"
@@ -710,7 +815,9 @@
   return {caller:caller};
 }
 
-assertEquals(23, _WASMEXP_.asmCompileRun(TestSwitch.toString()));
+assertEquals(23, _WASMEXP_.instantiateModuleFromAsm(
+      TestSwitch.toString()).caller());
+
 
 function TestSwitchFallthrough() {
   "use asm"
@@ -731,7 +838,9 @@
   return {caller:caller};
 }
 
-assertEquals(42, _WASMEXP_.asmCompileRun(TestSwitchFallthrough.toString()));
+assertEquals(42, _WASMEXP_.instantiateModuleFromAsm(
+      TestSwitchFallthrough.toString()).caller());
+
 
 function TestNestedSwitch() {
   "use asm"
@@ -756,7 +865,9 @@
   return {caller:caller};
 }
 
-assertEquals(43, _WASMEXP_.asmCompileRun(TestNestedSwitch.toString()));
+assertEquals(43, _WASMEXP_.instantiateModuleFromAsm(
+      TestNestedSwitch.toString()).caller());
+
 
 function TestInitFunctionWithNoGlobals() {
   "use asm";
@@ -771,6 +882,7 @@
 module.__init__();
 assertEquals(51, module.caller());
 
+
 function TestExportNameDifferentFromFunctionName() {
   "use asm";
   function caller() {
@@ -783,3 +895,458 @@
     TestExportNameDifferentFromFunctionName.toString());
 module.__init__();
 assertEquals(55, module.alt_caller());
+
+
+function TestFunctionTableSingleFunction() {
+  "use asm";
+
+  function dummy() {
+    return 71;
+  }
+
+  function caller() {
+    return function_table[0&0]() | 0;
+  }
+
+  var function_table = [dummy]
+
+  return {caller:caller};
+}
+
+assertEquals(71, _WASMEXP_.instantiateModuleFromAsm(
+      TestFunctionTableSingleFunction.toString()).caller());
+
+
+function TestFunctionTableMultipleFunctions() {
+  "use asm";
+
+  function inc1(x) {
+    x = x|0;
+    return (x+1)|0;
+  }
+
+  function inc2(x) {
+    x = x|0;
+    return (x+2)|0;
+  }
+
+  function caller() {
+    if (function_table[0&1](50) == 51) {
+      if (function_table[1&1](60) == 62) {
+        return 73;
+      }
+    }
+    return 0;
+  }
+
+  var function_table = [inc1, inc2]
+
+  return {caller:caller};
+}
+
+assertEquals(73, _WASMEXP_.instantiateModuleFromAsm(
+      TestFunctionTableMultipleFunctions.toString()).caller());
+
+
+function TestFunctionTable() {
+  "use asm";
+
+  function add(a, b) {
+    a = a|0;
+    b = b|0;
+    return (a+b)|0;
+  }
+
+  function sub(a, b) {
+    a = a|0;
+    b = b|0;
+    return (a-b)|0;
+  }
+
+  function inc(a) {
+    a = a|0;
+    return (a+1)|0;
+  }
+
+  function caller(table_id, fun_id, arg1, arg2) {
+    table_id = table_id|0;
+    fun_id = fun_id|0;
+    arg1 = arg1|0;
+    arg2 = arg2|0;
+    if (table_id == 0) {
+      return funBin[fun_id&3](arg1, arg2)|0;
+    } else if (table_id == 1) {
+      return fun[fun_id&0](arg1)|0;
+    }
+    return 0;
+  }
+
+  var funBin = [add, sub, sub, add];
+  var fun = [inc];
+
+  return {caller:caller};
+}
+
+var module = _WASMEXP_.instantiateModuleFromAsm(TestFunctionTable.toString());
+module.__init__();
+assertEquals(55, module.caller(0, 0, 33, 22));
+assertEquals(11, module.caller(0, 1, 33, 22));
+assertEquals(9, module.caller(0, 2, 54, 45));
+assertEquals(99, module.caller(0, 3, 54, 45));
+assertEquals(23, module.caller(0, 4, 12, 11));
+assertEquals(31, module.caller(1, 0, 30, 11));
+
+
+function TestForeignFunctions() {
+  function AsmModule(stdlib, foreign, buffer) {
+    "use asm";
+
+    var setVal = foreign.setVal;
+    var getVal = foreign.getVal;
+
+    function caller(initial_value, new_value) {
+      initial_value = initial_value|0;
+      new_value = new_value|0;
+      if ((getVal()|0) == (initial_value|0)) {
+        setVal(new_value|0);
+        return getVal()|0;
+      }
+      return 0;
+    }
+
+    return {caller:caller};
+  }
+
+  function ffi(initial_val) {
+    var val = initial_val;
+
+    function getVal() {
+      return val;
+    }
+
+    function setVal(new_val) {
+      val = new_val;
+    }
+
+    return {getVal:getVal, setVal:setVal};
+  }
+
+  var foreign = new ffi(23);
+
+  var module = _WASMEXP_.instantiateModuleFromAsm(AsmModule.toString(),
+                                                  foreign, null);
+
+  module.__init__();
+  assertEquals(103, module.caller(23, 103));
+}
+
+TestForeignFunctions();
+
+
+function TestForeignFunctionMultipleUse() {
+  function AsmModule(stdlib, foreign, buffer) {
+    "use asm";
+
+    var getVal = foreign.getVal;
+
+    function caller(int_val, double_val) {
+      int_val = int_val|0;
+      double_val = +double_val;
+      if ((getVal()|0) == (int_val|0)) {
+        if ((+getVal()) == (+double_val)) {
+          return 89;
+        }
+      }
+      return 0;
+    }
+
+    return {caller:caller};
+  }
+
+  function ffi() {
+    function getVal() {
+      return 83.25;
+    }
+
+    return {getVal:getVal};
+  }
+
+  var foreign = new ffi();
+
+  var module = _WASMEXP_.instantiateModuleFromAsm(AsmModule.toString(),
+                                                  foreign, null);
+
+  module.__init__();
+  assertEquals(89, module.caller(83, 83.25));
+}
+
+TestForeignFunctionMultipleUse();
+
+
+function TestForeignVariables() {
+  function AsmModule(stdlib, foreign, buffer) {
+    "use asm";
+
+    var i1 = foreign.foo | 0;
+    var f1 = +foreign.bar;
+    var i2 = foreign.baz | 0;
+    var f2 = +foreign.baz;
+
+    function geti1() {
+      return i1|0;
+    }
+
+    function getf1() {
+      return +f1;
+    }
+
+    function geti2() {
+      return i2|0;
+    }
+
+    function getf2() {
+      return +f2;
+    }
+
+    return {geti1:geti1, getf1:getf1, geti2:geti2, getf2:getf2};
+  }
+
+  function TestCase(env, i1, f1, i2, f2) {
+    var module = _WASMEXP_.instantiateModuleFromAsm(
+        AsmModule.toString(), env);
+    module.__init__();
+    assertEquals(i1, module.geti1());
+    assertEquals(f1, module.getf1());
+    assertEquals(i2, module.geti2());
+    assertEquals(f2, module.getf2());
+  }
+
+  // Check normal operation.
+  TestCase({foo: 123, bar: 234.5, baz: 345.7}, 123, 234.5, 345, 345.7);
+  // Check partial operation.
+  TestCase({baz: 345.7}, 0, NaN, 345, 345.7);
+  // Check that undefined values are converted to proper defaults.
+  TestCase({qux: 999}, 0, NaN, 0, NaN);
+  // Check that an undefined ffi is ok.
+  TestCase(undefined, 0, NaN, 0, NaN);
+  // Check that true values are converted properly.
+  TestCase({foo: true, bar: true, baz: true}, 1, 1.0, 1, 1.0);
+  // Check that false values are converted properly.
+  TestCase({foo: false, bar: false, baz: false}, 0, 0, 0, 0);
+  // Check that null values are converted properly.
+  TestCase({foo: null, bar: null, baz: null}, 0, 0, 0, 0);
+  // Check that string values are converted properly.
+  TestCase({foo: 'hi', bar: 'there', baz: 'dude'}, 0, NaN, 0, NaN);
+  TestCase({foo: '0xff', bar: '234', baz: '456.1'}, 255, 234, 456, 456.1, 456);
+  // Check that Date values are converted properly.
+  TestCase({foo: new Date(123), bar: new Date(456),
+            baz: new Date(789)}, 123, 456, 789, 789);
+  // Check that list values are converted properly.
+  TestCase({foo: [], bar: [], baz: []}, 0, 0, 0, 0);
+  // Check that object values are converted properly.
+  TestCase({foo: {}, bar: {}, baz: {}}, 0, NaN, 0, NaN);
+  // Check that getter object values are converted properly.
+  var o = {
+    get foo() {
+      return 123.4;
+    }
+  };
+  TestCase({foo: o.foo, bar: o.foo, baz: o.foo}, 123, 123.4, 123, 123.4);
+  // Check that getter object values are converted properly.
+  var o = {
+    get baz() {
+      return 123.4;
+    }
+  };
+  TestCase(o, 0, NaN, 123, 123.4);
+  // Check that objects with valueOf are converted properly.
+  var o = {
+    valueOf: function() { return 99; }
+  };
+  TestCase({foo: o, bar: o, baz: o}, 99, 99, 99, 99);
+  // Check that function values are converted properly.
+  TestCase({foo: TestCase, bar: TestCase, qux: TestCase}, 0, NaN, 0, NaN);
+  // Check that a missing ffi object is safe.
+  TestCase(undefined, 0, NaN, 0, NaN);
+}
+
+TestForeignVariables();
+
+
+(function() {
+  function TestByteHeapAccessCompat(stdlib, foreign, buffer) {
+    "use asm";
+
+    var HEAP8 = new stdlib.Uint8Array(buffer);
+    var HEAP32 = new stdlib.Int32Array(buffer);
+
+    function store(i, v) {
+      i = i | 0;
+      v = v | 0;
+      HEAP32[i >> 2] = v;
+    }
+
+    function storeb(i, v) {
+      i = i | 0;
+      v = v | 0;
+      HEAP8[i | 0] = v;
+    }
+
+    function load(i) {
+      i = i | 0;
+      return HEAP8[i] | 0;
+    }
+
+    function iload(i) {
+      i = i | 0;
+      return HEAP8[HEAP32[i >> 2] | 0] | 0;
+    }
+
+    return {load: load, iload: iload, store: store, storeb: storeb};
+  }
+
+  var m = _WASMEXP_.instantiateModuleFromAsm(
+      TestByteHeapAccessCompat.toString());
+  m.store(0, 20);
+  m.store(4, 21);
+  m.store(8, 22);
+  m.storeb(20, 123);
+  m.storeb(21, 42);
+  m.storeb(22, 77);
+  assertEquals(123, m.load(20));
+  assertEquals(42, m.load(21));
+  assertEquals(77, m.load(22));
+  assertEquals(123, m.iload(0));
+  assertEquals(42, m.iload(4));
+  assertEquals(77, m.iload(8));
+})();
+
+
+(function TestGlobalBlock() {
+  function Module(stdlib, foreign, buffer) {
+    "use asm";
+
+    var x = foreign.x | 0, y = foreign.y | 0;
+
+    function test() {
+      return (x + y) | 0;
+    }
+
+    return {test: test};
+  }
+
+  var m = _WASMEXP_.instantiateModuleFromAsm(
+      Module.toString(), { x: 4, y: 11 });
+  m.__init__();
+  assertEquals(15, m.test());
+})();
+
+
+(function TestComma() {
+  function CommaModule() {
+    "use asm";
+
+    function ifunc(a, b) {
+      a = +a;
+      b = b | 0;
+      return (a, b) | 0;
+    }
+
+    function dfunc(a, b) {
+      a = a | 0;
+      b = +b;
+      return +(a, b);
+    }
+
+    return {ifunc: ifunc, dfunc: dfunc};
+  }
+
+  var m = _WASMEXP_.instantiateModuleFromAsm(CommaModule.toString());
+  assertEquals(123, m.ifunc(456.7, 123));
+  assertEquals(123.4, m.dfunc(456, 123.4));
+})();
+
+
+(function TestOr() {
+  function Module() {
+    "use asm";
+    function func() {
+      var x = 1;
+      var y = 2;
+      return (x | y) | 0;
+    }
+    return {func: func};
+  }
+
+  var m = _WASMEXP_.instantiateModuleFromAsm(Module.toString());
+  assertEquals(3, m.func());
+})();
+
+
+(function TestAnd() {
+  function Module() {
+    "use asm";
+    function func() {
+      var x = 3;
+      var y = 2;
+      return (x & y) | 0;
+    }
+    return {func: func};
+  }
+
+  var m = _WASMEXP_.instantiateModuleFromAsm(Module.toString());
+  assertEquals(2, m.func());
+})();
+
+
+(function TestXor() {
+  function Module() {
+    "use asm";
+    function func() {
+      var x = 3;
+      var y = 2;
+      return (x ^ y) | 0;
+    }
+    return {func: func};
+  }
+
+  var m = _WASMEXP_.instantiateModuleFromAsm(Module.toString());
+  assertEquals(1, m.func());
+})();
+
+
+(function TestIntishAssignment() {
+  function Module(stdlib, foreign, heap) {
+    "use asm";
+    var HEAP32 = new stdlib.Int32Array(heap);
+    function func() {
+      var a = 1;
+      var b = 2;
+      HEAP32[0] = a + b;
+      return HEAP32[0] | 0;
+    }
+    return {func: func};
+  }
+
+  var m = _WASMEXP_.instantiateModuleFromAsm(Module.toString());
+  assertEquals(3, m.func());
+})();
+
+
+(function TestFloatishAssignment() {
+  function Module(stdlib, foreign, heap) {
+    "use asm";
+    var HEAPF32 = new stdlib.Float32Array(heap);
+    var fround = stdlib.Math.fround;
+    function func() {
+      var a = fround(1.0);
+      var b = fround(2.0);
+      HEAPF32[0] = a + b;
+      return +HEAPF32[0];
+    }
+    return {func: func};
+  }
+
+  var m = _WASMEXP_.instantiateModuleFromAsm(Module.toString());
+  assertEquals(3, m.func());
+})  // TODO(bradnelson): Enable when Math.fround implementation lands.
diff --git a/test/mjsunit/wasm/import-table.js b/test/mjsunit/wasm/import-table.js
new file mode 100644
index 0000000..33d1c35
--- /dev/null
+++ b/test/mjsunit/wasm/import-table.js
@@ -0,0 +1,387 @@
+// 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
+
+load("test/mjsunit/wasm/wasm-constants.js");
+
+function testCallImport(func, check) {
+  var kBodySize = 6;
+  var kNameFunOffset = 29 + kBodySize + 1;
+  var kNameMainOffset = kNameFunOffset + 4;
+
+  var ffi = new Object();
+  ffi.fun = func;
+
+  var data = bytes(
+    // signatures
+    kDeclSignatures, 1,
+    2, kAstI32, kAstF64, kAstF64, // (f64,f64) -> int
+    // -- main function
+    kDeclFunctions,
+    1,
+    kDeclFunctionName | kDeclFunctionExport,
+    0, 0,
+    kNameMainOffset, 0, 0, 0,    // name offset
+    kBodySize, 0,
+    // main body
+    kExprCallImport, 0,          // --
+    kExprGetLocal, 0,            // --
+    kExprGetLocal, 1,            // --
+    // imports
+    kDeclImportTable,
+    1,
+    0, 0,                        // sig index
+    0, 0, 0, 0,                  // module name offset
+    kNameFunOffset, 0, 0, 0,     // function name offset
+    // names
+    kDeclEnd,
+    'f', 'u', 'n', 0,            // --
+    'm', 'a', 'i', 'n', 0        // --
+  );
+
+  var module = _WASMEXP_.instantiateModule(data, ffi);
+
+  assertEquals("function", typeof module.main);
+
+  for (var i = 0; i < 100000; i += 10003) {
+    var a = 22.5 + i, b = 10.5 + i;
+    var r = module.main(a, b);
+    check(r, a, b);
+  }
+}
+
+var global = (function() { return this; })();
+var params = [-99, -99, -99, -99];
+var was_called = false;
+var length = -1;
+
+function FOREIGN_SUB(a, b) {
+  print("FOREIGN_SUB(" + a + ", " + b + ")");
+  was_called = true;
+  params[0] = this;
+  params[1] = a;
+  params[2] = b;
+  return (a - b) | 0;
+}
+
+function check_FOREIGN_SUB(r, a, b) {
+    assertEquals(a - b | 0, r);
+    assertTrue(was_called);
+//    assertEquals(global, params[0]);  // sloppy mode
+    assertEquals(a, params[1]);
+    assertEquals(b, params[2]);
+    was_called = false;
+}
+
+testCallImport(FOREIGN_SUB, check_FOREIGN_SUB);
+
+
+function FOREIGN_ABCD(a, b, c, d) {
+  print("FOREIGN_ABCD(" + a + ", " + b + ", " + c + ", " + d + ")");
+  was_called = true;
+  params[0] = this;
+  params[1] = a;
+  params[2] = b;
+  params[3] = c;
+  params[4] = d;
+  return (a * b * 6) | 0;
+}
+
+function check_FOREIGN_ABCD(r, a, b) {
+    assertEquals((a * b * 6) | 0, r);
+    assertTrue(was_called);
+//    assertEquals(global, params[0]);  // sloppy mode.
+    assertEquals(a, params[1]);
+    assertEquals(b, params[2]);
+    assertEquals(undefined, params[3]);
+    assertEquals(undefined, params[4]);
+    was_called = false;
+}
+
+testCallImport(FOREIGN_ABCD, check_FOREIGN_ABCD);
+
+function FOREIGN_ARGUMENTS0() {
+  print("FOREIGN_ARGUMENTS0");
+  was_called = true;
+  length = arguments.length;
+  for (var i = 0; i < arguments.length; i++) {
+    params[i] = arguments[i];
+  }
+  return (arguments[0] * arguments[1] * 7) | 0;
+}
+
+function FOREIGN_ARGUMENTS1(a) {
+  print("FOREIGN_ARGUMENTS1", a);
+  was_called = true;
+  length = arguments.length;
+  for (var i = 0; i < arguments.length; i++) {
+    params[i] = arguments[i];
+  }
+  return (arguments[0] * arguments[1] * 7) | 0;
+}
+
+function FOREIGN_ARGUMENTS2(a, b) {
+  print("FOREIGN_ARGUMENTS2", a, b);
+  was_called = true;
+  length = arguments.length;
+  for (var i = 0; i < arguments.length; i++) {
+    params[i] = arguments[i];
+  }
+  return (a * b * 7) | 0;
+}
+
+function FOREIGN_ARGUMENTS3(a, b, c) {
+  print("FOREIGN_ARGUMENTS3", a, b, c);
+  was_called = true;
+  length = arguments.length;
+  for (var i = 0; i < arguments.length; i++) {
+    params[i] = arguments[i];
+  }
+  return (a * b * 7) | 0;
+}
+
+function FOREIGN_ARGUMENTS4(a, b, c, d) {
+  print("FOREIGN_ARGUMENTS4", a, b, c, d);
+  was_called = true;
+  length = arguments.length;
+  for (var i = 0; i < arguments.length; i++) {
+    params[i] = arguments[i];
+  }
+  return (a * b * 7) | 0;
+}
+
+function check_FOREIGN_ARGUMENTS(r, a, b) {
+  assertEquals((a * b * 7) | 0, r);
+  assertTrue(was_called);
+  assertEquals(2, length);
+  assertEquals(a, params[0]);
+  assertEquals(b, params[1]);
+  was_called = false;
+}
+
+// Check a bunch of uses of the arguments object.
+testCallImport(FOREIGN_ARGUMENTS0, check_FOREIGN_ARGUMENTS);
+testCallImport(FOREIGN_ARGUMENTS1, check_FOREIGN_ARGUMENTS);
+testCallImport(FOREIGN_ARGUMENTS2, check_FOREIGN_ARGUMENTS);
+testCallImport(FOREIGN_ARGUMENTS3, check_FOREIGN_ARGUMENTS);
+testCallImport(FOREIGN_ARGUMENTS4, check_FOREIGN_ARGUMENTS);
+
+function returnValue(val) {
+  return function(a, b) {
+    print("RETURN_VALUE ", val);
+    return val;
+  }
+}
+
+
+function checkReturn(expected) {
+  return function(r, a, b) { assertEquals(expected, r); }
+}
+
+// Check that returning weird values doesn't crash
+testCallImport(returnValue(undefined), checkReturn(0));
+testCallImport(returnValue(null), checkReturn(0));
+testCallImport(returnValue("0"), checkReturn(0));
+testCallImport(returnValue("-77"), checkReturn(-77));
+
+var objWithValueOf = {valueOf: function() { return 198; }}
+
+testCallImport(returnValue(objWithValueOf), checkReturn(198));
+
+
+function testCallBinopVoid(type, func, check) {
+  var kBodySize = 10;
+  var kNameFunOffset = 28 + kBodySize + 1;
+  var kNameMainOffset = kNameFunOffset + 4;
+
+  var ffi = new Object();
+
+  var passed_length = -1;
+  var passed_a = -1;
+  var passed_b = -1;
+  var args_a = -1;
+  var args_b = -1;
+
+  ffi.fun = function(a, b) {
+    passed_length = arguments.length;
+    passed_a = a;
+    passed_b = b;
+    args_a = arguments[0];
+    args_b = arguments[1];
+  }
+
+  var data = bytes(
+    // -- signatures
+    kDeclSignatures, 2,
+    2, kAstStmt, type, type,    // (type,type)->void
+    2, kAstI32, type, type,     // (type,type)->int
+    // -- foreign function
+    kDeclFunctions, 2,
+    kDeclFunctionName | kDeclFunctionImport,
+    0, 0,                       // signature index
+    kNameFunOffset, 0, 0, 0,    // name offset
+    // -- main function
+    kDeclFunctionName | kDeclFunctionExport,
+    1, 0,                       // signature index
+    kNameMainOffset, 0, 0, 0,   // name offset
+    kBodySize, 0,               // body size
+    // main body
+    kExprBlock, 2,              // --
+    kExprCallFunction, 0,       // --
+    kExprGetLocal, 0,           // --
+    kExprGetLocal, 1,           // --
+    kExprI8Const, 99,           // --
+    // names
+    kDeclEnd,
+    'f', 'u', 'n', 0,           // --
+    'm', 'a', 'i', 'n', 0       // --
+  );
+
+  var module = _WASMEXP_.instantiateModule(data, ffi);
+
+  assertEquals("function", typeof module.main);
+
+  print("testCallBinopVoid", type);
+
+  for (var i = 0; i < 100000; i += 10003.1) {
+    var a = 22.5 + i, b = 10.5 + i;
+    var r = module.main(a, b);
+    assertEquals(99, r);
+    assertEquals(2, passed_length);
+    var expected_a, expected_b;
+    switch (type) {
+      case kAstI32: {
+        expected_a = a | 0;
+        expected_b = b | 0;
+        break;
+      }
+      case kAstF32: {
+        expected_a = Math.fround(a);
+        expected_b = Math.fround(b);
+        break;
+      }
+      case kAstF64: {
+        expected_a = a;
+        expected_b = b;
+        break;
+      }
+    }
+
+    assertEquals(expected_a, args_a);
+    assertEquals(expected_b, args_b);
+    assertEquals(expected_a, passed_a);
+    assertEquals(expected_b, passed_b);
+  }
+}
+
+
+testCallBinopVoid(kAstI32);
+// TODO testCallBinopVoid(kAstI64);
+testCallBinopVoid(kAstF32);
+testCallBinopVoid(kAstF64);
+
+
+
+function testCallPrint() {
+  var kBodySize = 10;
+  var kNamePrintOffset = 10 + 7 + 7 + 9 + kBodySize + 1;
+  var kNameMainOffset = kNamePrintOffset + 6;
+
+  var ffi = new Object();
+  ffi.print = print;
+
+  var data = bytes(
+    // -- signatures
+    kDeclSignatures, 2,
+    1, kAstStmt, kAstI32,       // i32->void
+    1, kAstStmt, kAstF64,       // f64->int
+    kDeclFunctions, 3,
+    // -- import print i32
+    kDeclFunctionName | kDeclFunctionImport,
+    0, 0,                       // signature index
+    kNamePrintOffset, 0, 0, 0,  // name offset
+    // -- import print f64
+    kDeclFunctionName | kDeclFunctionImport,
+    1, 0,                       // signature index
+    kNamePrintOffset, 0, 0, 0,  // name offset
+    // -- decl main
+    kDeclFunctionName | kDeclFunctionExport,
+    1, 0,                       // signature index
+    kNameMainOffset, 0, 0, 0,   // name offset
+    kBodySize, 0,               // body size
+    // main body
+    kExprBlock, 2,              // --
+    kExprCallFunction, 0,       // --
+    kExprI8Const, 97,           // --
+    kExprCallFunction, 1,       // --
+    kExprGetLocal, 0,           // --
+    // names
+    kDeclEnd,
+    'p', 'r', 'i', 'n', 't', 0, // --
+    'm', 'a', 'i', 'n', 0       // --
+  );
+
+  var module = _WASMEXP_.instantiateModule(data, ffi);
+
+  assertEquals("function", typeof module.main);
+
+  for (var i = -9; i < 900; i += 6.125) {
+      module.main(i);
+  }
+}
+
+testCallPrint();
+testCallPrint();
+
+
+function testCallImport2(foo, bar, expected) {
+  var kBodySize = 5;
+  var kNameFooOffset = 37 + kBodySize + 1;
+  var kNameBarOffset = kNameFooOffset + 4;
+  var kNameMainOffset = kNameBarOffset + 4;
+
+  var ffi = new Object();
+  ffi.foo = foo;
+  ffi.bar = bar;
+
+  var data = bytes(
+    // signatures
+    kDeclSignatures, 1,
+    0, kAstI32,                  // void -> i32
+    // -- main function
+    kDeclFunctions,
+    1,
+    kDeclFunctionName | kDeclFunctionExport,
+    0, 0,
+    kNameMainOffset, 0, 0, 0,    // name offset
+    kBodySize, 0,
+    // main body
+    kExprI32Add,                 // --
+    kExprCallImport, 0,          // --
+    kExprCallImport, 1,          // --
+    // imports
+    kDeclImportTable,
+    2,
+    0, 0,                        // sig index
+    0, 0, 0, 0,                  // module name offset
+    kNameFooOffset, 0, 0, 0,     // function name offset
+    0, 0,                        // sig index
+    0, 0, 0, 0,                  // module name offset
+    kNameBarOffset, 0, 0, 0,     // function name offset
+    // names
+    kDeclEnd,
+    'f', 'o', 'o', 0,            // --
+    'b', 'a', 'r', 0,            // --
+    'm', 'a', 'i', 'n', 0        // --
+  );
+
+  var module = _WASMEXP_.instantiateModule(data, ffi);
+
+  assertEquals("function", typeof module.main);
+
+  assertEquals(expected, module.main());
+}
+
+testCallImport2(function() { return 33; }, function () { return 44; }, 77);
diff --git a/test/mjsunit/wasm/compile-run-basic.js b/test/mjsunit/wasm/instantiate-run-basic.js
similarity index 91%
rename from test/mjsunit/wasm/compile-run-basic.js
rename to test/mjsunit/wasm/instantiate-run-basic.js
index dbc624a..b103e8f 100644
--- a/test/mjsunit/wasm/compile-run-basic.js
+++ b/test/mjsunit/wasm/instantiate-run-basic.js
@@ -28,4 +28,4 @@
   'm', 'a', 'i', 'n', 0       // name
 );
 
-assertEquals(kReturnValue, _WASMEXP_.compileRun(data));
+assertEquals(kReturnValue, _WASMEXP_.instantiateModule(data).main());
diff --git a/test/mjsunit/wasm/stack.js b/test/mjsunit/wasm/stack.js
new file mode 100644
index 0000000..d4b72c0
--- /dev/null
+++ b/test/mjsunit/wasm/stack.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");
+
+function testStack(func, check) {
+  var kBodySize = 2;
+  var kNameFunOffset = 22 + kBodySize + 1;
+  var kNameMainOffset = kNameFunOffset + 4;
+
+  var ffi = new Object();
+  ffi.fun = func;
+
+  var data = bytes(
+      // signatures
+      kDeclSignatures, 1,  //  --
+      0, kAstStmt,         // () -> void
+      // -- foreign function
+      kDeclFunctions, 2,                        //  --
+      kDeclFunctionName | kDeclFunctionImport,  // --
+      0, 0,                                     //  --
+      kNameFunOffset, 0, 0, 0,                  // name offset
+      // -- main function
+      kDeclFunctionName | kDeclFunctionExport,  // --
+      0, 0,                                     //  --
+      kNameMainOffset, 0, 0, 0,                 // name offset
+      kBodySize, 0,
+      // main body
+      kExprCallFunction, 0,  // --
+      // names
+      kDeclEnd,              //  --
+      'f', 'u', 'n', 0,      //  --
+      'm', 'a', 'i', 'n', 0  //  --
+      );
+
+  var module = _WASMEXP_.instantiateModule(data, ffi);
+
+  assertEquals("function", typeof module.main);
+
+  module.main();
+  check();
+}
+
+// The stack trace contains file path, only keep "stack.js".
+function stripPath(s) {
+  return s.replace(/[^ (]*stack\.js/g, "stack.js");
+}
+
+var stack;
+function STACK() {
+  var e = new Error();
+  stack = e.stack;
+}
+
+function check_STACK() {
+  assertEquals(expected, stripPath(stack));
+}
+
+var expected = "Error\n" +
+    // The line numbers below will change as this test gains / loses lines..
+    "    at STACK (stack.js:54:11)\n" +  // --
+    "    at testStack (stack.js:43:10)\n" +
+    // TODO(jfb) Add WebAssembly stack here.
+    "    at stack.js:69:1";
+
+testStack(STACK, check_STACK);
diff --git a/test/mjsunit/wasm/start-function.js b/test/mjsunit/wasm/start-function.js
new file mode 100644
index 0000000..4008efa
--- /dev/null
+++ b/test/mjsunit/wasm/start-function.js
@@ -0,0 +1,172 @@
+// Copyright 2016 the V8 project 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");
+
+function instantiate(sig, body) {
+  var module = new Array();
+  module = module.concat([
+    // -- signatures
+    kDeclSignatures, 1,
+  ]);
+  module = module.concat(sig);
+  module = module.concat([
+    // -- functions
+    kDeclFunctions, 1,
+    0,                 // decl flags
+    0, 0,              // signature
+    body.length, 0,    // body size
+  ]);
+  module = module.concat(body);
+  module = module.concat([
+    // -- declare start function
+    kDeclStartFunction,
+    0
+  ]);
+
+  var data = bytes.apply(this, module);
+  print(module);
+  print(data instanceof ArrayBuffer);
+  print(data.byteLength);
+  return _WASMEXP_.instantiateModule(data);
+}
+
+function assertFails(sig, body) {
+  try {
+    var module = instantiate(sig, body);
+    print("expected failure, but passes");
+    assertFalse(true);
+  } catch (expected) {
+    print("ok: " + expected);
+  }
+}
+
+function assertVerifies(sig, body) {
+  var module = instantiate(sig, body);
+  assertFalse(module === undefined);
+  assertFalse(module === null);
+  assertFalse(module === 0);
+  assertEquals("object", typeof module);
+  return module;
+}
+
+assertVerifies([0, kAstStmt], [kExprNop]);
+assertVerifies([0, kAstI32], [kExprI8Const, 0]);
+
+// Arguments aren't allow to start functions.
+assertFails([1, kAstI32, kAstI32], [kExprGetLocal, 0]);
+assertFails([2, kAstI32, kAstI32, kAstF32], [kExprGetLocal, 0]);
+assertFails([3, kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]);
+
+(function testInvalidIndex() {
+  var kBodySize = 1;
+  var data = bytes(
+    // -- signatures
+    kDeclSignatures, 1,
+    0, kAstStmt,
+    // -- functions
+    kDeclFunctions, 1,
+    0,                 // decl flags
+    0, 0,              // signature
+    kBodySize, 0,      // body size
+    kExprNop,          // body
+    // -- declare start function
+    kDeclStartFunction,
+    1
+  );
+
+  assertThrows(function() { _WASMEXP_.instantiateModule(data); });
+})();
+
+
+(function testTwoStartFuncs() {
+  var kBodySize = 1;
+  var data = bytes(
+    // -- signatures
+    kDeclSignatures, 1,
+    0, kAstStmt,
+    // -- functions
+    kDeclFunctions, 1,
+    0,                 // decl flags
+    0, 0,              // signature
+    kBodySize, 0,      // body size
+    kExprNop,          // body
+    // -- declare start function
+    kDeclStartFunction,
+    0,
+    // -- declare start function
+    kDeclStartFunction,
+    0
+  );
+
+  assertThrows(function() { _WASMEXP_.instantiateModule(data); });
+})();
+
+
+(function testRun() {
+  var kBodySize = 6;
+
+  var data = bytes(
+    kDeclMemory,
+    12, 12, 1,                  // memory
+    // -- signatures
+    kDeclSignatures, 1,
+    0, kAstStmt,
+    // -- start function
+    kDeclFunctions, 1,
+    0,                          // decl flags
+    0, 0,                       // signature
+    kBodySize, 0,               // code size
+    // -- start body
+    kExprI32StoreMem, 0, kExprI8Const, 0, kExprI8Const, 77,
+    // -- declare start function
+    kDeclStartFunction,
+    0
+  );
+
+  var module = _WASMEXP_.instantiateModule(data);
+  var memory = module.memory;
+  var view = new Int8Array(memory);
+  assertEquals(77, view[0]);
+})();
+
+(function testStartFFI() {
+  var kBodySize = 2;
+  var kNameOffset = 4 + 9 + 7 + 3;
+
+  var data = bytes(
+    // -- signatures
+    kDeclSignatures, 1,
+    0, kAstStmt,
+    // -- imported function
+    kDeclFunctions, 2,
+    kDeclFunctionImport | kDeclFunctionName,     // decl flags
+    0, 0,                       // signature
+    kNameOffset, 0, 0, 0,
+    // -- start function
+    0,                          // decl flags
+    0, 0,                       // signature
+    kBodySize, 0,               // code size
+    // -- start body
+    kExprCallFunction, 0,
+    // -- declare start function
+    kDeclStartFunction,
+    1,
+    kDeclEnd,
+    'f', 'o', 'o', 0
+  );
+
+  var ranned = false;
+  var ffi = new Object();
+  ffi.foo = function() {
+    print("we ranned at stert!");
+    ranned = true;
+  }
+  var module = _WASMEXP_.instantiateModule(data, ffi);
+  var memory = module.memory;
+  var view = new Int8Array(memory);
+  assertTrue(ranned);
+})();
diff --git a/test/mjsunit/wasm/wasm-constants.js b/test/mjsunit/wasm/wasm-constants.js
index 4b710f1..458b51a 100644
--- a/test/mjsunit/wasm/wasm-constants.js
+++ b/test/mjsunit/wasm/wasm-constants.js
@@ -22,6 +22,8 @@
 var kDeclGlobals = 0x03;
 var kDeclDataSegments = 0x04;
 var kDeclFunctionTable = 0x05;
+var kDeclStartFunction = 0x07;
+var kDeclImportTable = 0x08;
 var kDeclEnd = 0x06;
 
 // Function declaration flags
@@ -61,6 +63,7 @@
 var kExprStoreGlobal = 0x11;
 var kExprCallFunction = 0x12;
 var kExprCallIndirect = 0x13;
+var kExprCallImport = 0x1F;
 
 var kExprI32LoadMem8S = 0x20;
 var kExprI32LoadMem8U = 0x21;
diff --git a/test/mjsunit/wasm/wasm-object-api.js b/test/mjsunit/wasm/wasm-object-api.js
index 1dfbb65..8912271 100644
--- a/test/mjsunit/wasm/wasm-object-api.js
+++ b/test/mjsunit/wasm/wasm-object-api.js
@@ -8,4 +8,5 @@
 assertFalse(undefined == _WASMEXP_);
 assertEquals("function", typeof _WASMEXP_.verifyModule);
 assertEquals("function", typeof _WASMEXP_.verifyFunction);
-assertEquals("function", typeof _WASMEXP_.compileRun);
+assertEquals("function", typeof _WASMEXP_.instantiateModule);
+assertEquals("function", typeof _WASMEXP_.instantiateModuleFromAsm);
diff --git a/test/optimize_for_size.isolate b/test/optimize_for_size.isolate
index aa7f570..16b9315 100644
--- a/test/optimize_for_size.isolate
+++ b/test/optimize_for_size.isolate
@@ -2,6 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 {
+  'variables': {
+    'command': [
+      '../tools/run-tests.py',
+    ],
+  },
   'includes': [
     'cctest/cctest.isolate',
     'intl/intl.isolate',
diff --git a/test/perf.gyp b/test/perf.gyp
new file mode 100644
index 0000000..ff84606
--- /dev/null
+++ b/test/perf.gyp
@@ -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.
+
+{
+  'conditions': [
+    ['test_isolation_mode != "noop"', {
+      'targets': [
+        {
+          'target_name': 'perf_run',
+          'type': 'none',
+          'dependencies': [
+            'cctest/cctest.gyp:cctest_exe_run',
+            '../src/d8.gyp:d8_run',
+          ],
+          'includes': [
+            '../build/features.gypi',
+            '../build/isolate.gypi',
+          ],
+          'sources': [
+            'perf.isolate',
+          ],
+        },
+      ],
+    }],
+  ],
+}
diff --git a/test/perf.isolate b/test/perf.isolate
new file mode 100644
index 0000000..77f66cc
--- /dev/null
+++ b/test/perf.isolate
@@ -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.
+{
+  'variables': {
+    'command': [
+      '../tools/run_perf.py',
+    ],
+    'files': [
+      '../tools/run_perf.py',
+      # This is often used to trigger performance bots. We include it in the
+      # isolate to not get these builds deduped.
+      '../tools/whitespace.txt',
+      'js-perf-test/',
+      'memory/',
+      'simdjs/',
+    ],
+  },
+  'includes': [
+    'cctest/cctest_exe.isolate',
+    '../src/d8.isolate',
+  ],
+}
diff --git a/test/test262/archive.py b/test/test262/archive.py
new file mode 100755
index 0000000..8398e51
--- /dev/null
+++ b/test/test262/archive.py
@@ -0,0 +1,18 @@
+#!/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
+import tarfile
+
+os.chdir(os.path.dirname(os.path.abspath(__file__)))
+
+def filter_git(tar_info):
+  if tar_info.name.startswith(os.path.join('data', '.git')):
+    return None
+  else:
+    return tar_info
+
+with tarfile.open('data.tar', 'w') as tar:
+  tar.add('data', filter=filter_git)
diff --git a/test/test262/list.py b/test/test262/list.py
new file mode 100755
index 0000000..69ca62c
--- /dev/null
+++ b/test/test262/list.py
@@ -0,0 +1,15 @@
+#!/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
+import tarfile
+
+os.chdir(os.path.dirname(os.path.abspath(__file__)))
+
+for root, dirs, files in os.walk("data"):
+  dirs[:] = [d for d in dirs if not d.endswith('.git')]
+  for name in files:
+    # These names are for gyp, which expects slashes on all platforms.
+    print('/'.join(root.split(os.sep) + [name]))
diff --git a/test/test262/test262.gyp b/test/test262/test262.gyp
index 45e6bc7..5d79add 100644
--- a/test/test262/test262.gyp
+++ b/test/test262/test262.gyp
@@ -19,6 +19,14 @@
           'sources': [
             'test262.isolate',
           ],
+          'actions': [
+            {
+              'action_name': 'archive_test262',
+              'inputs': ['archive.py', '<!@(python list.py)'],
+              'outputs': ['data.tar'],
+              'action': ['python', 'archive.py'],
+            },
+          ],
         },
       ],
     }],
diff --git a/test/test262/test262.isolate b/test/test262/test262.isolate
index dbeca5e..0ac045a 100644
--- a/test/test262/test262.isolate
+++ b/test/test262/test262.isolate
@@ -4,11 +4,14 @@
 {
   'variables': {
     'files': [
-      './',
+      'data.tar',
+      'harness-adapt.js',
+      'test262.status',
+      'testcfg.py',
     ],
   },
   'includes': [
     '../../src/d8.isolate',
     '../../tools/testrunner/testrunner.isolate',
   ],
-}
\ No newline at end of file
+}
diff --git a/test/test262/test262.status b/test/test262/test262.status
index a7f76a4..a926bcc 100644
--- a/test/test262/test262.status
+++ b/test/test262/test262.status
@@ -33,9 +33,6 @@
   'intl402/11.2.3_b': [FAIL],
   'intl402/12.2.3_b': [FAIL],
 
-  # Unicode canonicalization is not available with i18n turned off.
-  'built-ins/String/prototype/localeCompare/15.5.4.9_CE': [['no_i18n', SKIP]],
-
   ###################### NEEDS INVESTIGATION #######################
 
   # Possibly same cause as S8.5_A2.1, below: floating-point tests.
@@ -50,43 +47,10 @@
 
   ###################### MISSING ES6 FEATURES #######################
 
-  # It's unclear what the right behavior for [[Enumerate]] is; we're awaiting
-  # clarification in the spec. Currently, our for-in implementation for
-  # Proxies checks all trap result values for being strings...
-  'built-ins/Proxy/enumerate/return-trap-result': [FAIL],
-  # ...and our Reflect.enumerate implementation is built on for-in by wrapping
-  # the iteration's results in a new generator; this postpones exceptions.
-  'built-ins/Reflect/enumerate/return-abrupt-from-result': [FAIL],
-
-  # https://code.google.com/p/v8/issues/detail?id=4093
-  'built-ins/Array/symbol-species': [FAIL],
-  'built-ins/Array/symbol-species-name': [FAIL],
-  'built-ins/ArrayBuffer/symbol-species': [FAIL],
-  'built-ins/ArrayBuffer/symbol-species-name': [FAIL],
-  'built-ins/ArrayBuffer/prototype/slice/species-constructor-is-not-object': [FAIL],
-  'built-ins/ArrayBuffer/prototype/slice/species-returns-smaller-arraybuffer': [FAIL],
-  'built-ins/ArrayBuffer/prototype/slice/species-is-not-object': [FAIL],
-  'built-ins/ArrayBuffer/prototype/slice/species-is-not-constructor': [FAIL],
-  'built-ins/ArrayBuffer/prototype/slice/species-returns-larger-arraybuffer': [FAIL],
-  'built-ins/ArrayBuffer/prototype/slice/species-returns-not-arraybuffer': [FAIL],
-  'built-ins/ArrayBuffer/prototype/slice/species-returns-same-arraybuffer': [FAIL],
-  'built-ins/ArrayBuffer/prototype/slice/species': [FAIL],
-  'built-ins/Map/symbol-species': [FAIL],
-  'built-ins/Map/symbol-species-name': [FAIL],
-  'built-ins/Promise/Symbol.species/prop-desc': [FAIL],
-  'built-ins/Promise/Symbol.species/return-value': [FAIL],
-  'built-ins/Promise/all/species-get-error': [PASS, FAIL],
-  'built-ins/Promise/prototype/then/ctor-custom': [FAIL],
-  'built-ins/Promise/race/species-get-error': [PASS, FAIL],
-  'built-ins/Promise/symbol-species': [FAIL],
-  'built-ins/Promise/symbol-species-name': [FAIL],
-  'built-ins/RegExp/symbol-species': [FAIL],
-  'built-ins/RegExp/symbol-species-name': [FAIL],
-  'built-ins/Set/symbol-species': [FAIL],
-  'built-ins/Set/symbol-species-name': [FAIL],
-  'built-ins/Symbol/species/basic': [FAIL],
-  'built-ins/Symbol/species/builtin-getter-name': [FAIL],
-  'built-ins/Symbol/species/subclassing': [FAIL],
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4768
+  # The Reflect.enumerate trap is removed
+  'built-ins/Reflect/enumerate/*': [SKIP],
+  'built-ins/Proxy/enumerate/*': [SKIP],
 
   # https://code.google.com/p/v8/issues/detail?id=4163
   'built-ins/GeneratorPrototype/next/context-constructor-invocation': [FAIL],
@@ -99,6 +63,7 @@
   'built-ins/Map/iterator-item-second-entry-returns-abrupt': [FAIL],
   'built-ins/Map/iterator-items-are-not-object-close-iterator': [FAIL],
   'built-ins/Promise/all/iter-close': [FAIL],
+  'built-ins/Promise/race/iter-close': [PASS, FAIL],
   'built-ins/Set/set-iterator-close-after-add-failure': [FAIL],
   'built-ins/WeakMap/iterator-close-after-set-failure': [FAIL],
   'built-ins/WeakMap/iterator-item-first-entry-returns-abrupt': [FAIL],
@@ -106,15 +71,6 @@
   'built-ins/WeakMap/iterator-items-are-not-object-close-iterator': [FAIL],
   'built-ins/WeakSet/iterator-close-after-add-failure': [FAIL],
 
-  # https://code.google.com/p/v8/issues/detail?id=4119
-  'built-ins/RegExp/call_with_non_regexp_same_constructor': [FAIL],
-  'built-ins/RegExp/from-regexp-like-short-circuit': [FAIL],
-  'built-ins/RegExp/from-regexp-like': [FAIL],
-  'built-ins/RegExp/from-regexp-like-flag-override': [FAIL],
-  'built-ins/RegExp/from-regexp-like-get-source-err': [FAIL],
-  'built-ins/RegExp/from-regexp-like-get-flags-err': [FAIL],
-  'built-ins/RegExp/from-regexp-like-get-ctor-err': [FAIL],
-
   # https://code.google.com/p/v8/issues/detail?id=4348
   'built-ins/String/prototype/Symbol.iterator/this-val-non-obj-coercible': [FAIL],
 
@@ -148,24 +104,6 @@
   'built-ins/Array/prototype/values/iteration-mutable': [FAIL],
   'built-ins/Array/prototype/Symbol.unscopables/value': [FAIL],
 
-  # https://code.google.com/p/v8/issues/detail?id=3566
-  'built-ins/GeneratorPrototype/return/from-state-completed': [FAIL],
-  'built-ins/GeneratorPrototype/return/from-state-suspended-start': [FAIL],
-  'built-ins/GeneratorPrototype/return/property-descriptor': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-catch-before-try': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-catch-following-catch': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-catch-within-catch': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-catch-within-try': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-finally-before-try': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-finally-following-finally': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-catch': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-finally': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-inner-try': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-after-nested': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-before-nested': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-finally-within-finally': [FAIL],
-  'built-ins/GeneratorPrototype/return/try-finally-within-try': [FAIL],
-
   # https://code.google.com/p/v8/issues/detail?id=4248
   'language/expressions/compound-assignment/S11.13.2_A5.*': [FAIL],
   'language/expressions/compound-assignment/S11.13.2_A6.*': [FAIL],
@@ -194,71 +132,13 @@
   'language/expressions/assignment/S11.13.1_A5*': [FAIL],
   'language/expressions/assignment/S11.13.1_A6*': [FAIL],
 
-  # https://code.google.com/p/v8/issues/detail?id=3699
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4709
   'built-ins/Proxy/revocable/revocation-function-name': [FAIL],
-  'language/expressions/assignment/destructuring/array-elem-init-fn-name-arrow': [FAIL],
-  'language/expressions/assignment/destructuring/array-elem-init-fn-name-class': [FAIL],
-  'language/expressions/assignment/destructuring/array-elem-init-fn-name-cover': [FAIL],
-  'language/expressions/assignment/destructuring/array-elem-init-fn-name-fn': [FAIL],
-  'language/expressions/assignment/destructuring/array-elem-init-fn-name-gen': [FAIL],
-  'language/expressions/assignment/destructuring/obj-id-init-fn-name-arrow': [FAIL],
-  'language/expressions/assignment/destructuring/obj-id-init-fn-name-class': [FAIL],
-  'language/expressions/assignment/destructuring/obj-id-init-fn-name-cover': [FAIL],
-  'language/expressions/assignment/destructuring/obj-id-init-fn-name-fn': [FAIL],
-  'language/expressions/assignment/destructuring/obj-id-init-fn-name-gen': [FAIL],
-  'language/expressions/assignment/destructuring/obj-prop-elem-init-fn-name-arrow': [FAIL],
-  'language/expressions/assignment/destructuring/obj-prop-elem-init-fn-name-class': [FAIL],
-  'language/expressions/assignment/destructuring/obj-prop-elem-init-fn-name-cover': [FAIL],
-  'language/expressions/assignment/destructuring/obj-prop-elem-init-fn-name-fn': [FAIL],
-  'language/expressions/assignment/destructuring/obj-prop-elem-init-fn-name-gen': [FAIL],
-  'language/expressions/assignment/fn-name-arrow': [FAIL],
-  'language/expressions/assignment/fn-name-class': [FAIL],
-  'language/expressions/assignment/fn-name-cover': [FAIL],
-  'language/expressions/assignment/fn-name-fn': [FAIL],
-  'language/expressions/assignment/fn-name-gen': [FAIL],
   'language/expressions/assignment/fn-name-lhs-cover': [FAIL],
   'language/expressions/assignment/fn-name-lhs-member': [FAIL],
   'language/expressions/class/name': [FAIL],
   'language/expressions/function/name': [FAIL],
-  'language/expressions/generators/implicit-name': [FAIL],
   'language/expressions/generators/name': [FAIL],
-  'language/expressions/generators/name-property-descriptor': [FAIL],
-  'language/expressions/object/fn-name-accessor-get': [FAIL],
-  'language/expressions/object/fn-name-accessor-set': [FAIL],
-  'language/expressions/object/fn-name-arrow': [FAIL],
-  'language/expressions/object/fn-name-class': [FAIL],
-  'language/expressions/object/fn-name-cover': [FAIL],
-  'language/expressions/object/fn-name-fn': [FAIL],
-  'language/expressions/object/fn-name-gen': [FAIL],
-  'language/expressions/object/fn-name-lhs-cover': [FAIL],
-  'language/expressions/object/fn-name-lhs-member': [FAIL],
-  'language/expressions/object/method-definition/fn-name-accessor-get': [FAIL],
-  'language/expressions/object/method-definition/fn-name-accessor-set': [FAIL],
-  'language/expressions/object/method-definition/fn-name-arrow': [FAIL],
-  'language/expressions/object/method-definition/fn-name-class': [FAIL],
-  'language/expressions/object/method-definition/fn-name-cover': [FAIL],
-  'language/expressions/object/method-definition/fn-name-fn': [FAIL],
-  'language/expressions/object/method-definition/fn-name-gen': [FAIL],
-  'language/statements/class/definition/basics': [FAIL],
-  'language/statements/class/definition/fn-name-accessor-get': [FAIL],
-  'language/statements/class/definition/fn-name-accessor-set': [FAIL],
-  'language/statements/class/definition/fn-name-gen-method': [FAIL],
-  'language/statements/class/definition/fn-name-method': [FAIL],
-  'language/statements/const/fn-name-arrow': [FAIL],
-  'language/statements/const/fn-name-class': [FAIL],
-  'language/statements/const/fn-name-cover': [FAIL],
-  'language/statements/const/fn-name-fn': [FAIL],
-  'language/statements/const/fn-name-gen': [FAIL],
-  'language/statements/let/fn-name-arrow': [FAIL],
-  'language/statements/let/fn-name-class': [FAIL],
-  'language/statements/let/fn-name-cover': [FAIL],
-  'language/statements/let/fn-name-fn': [FAIL],
-  'language/statements/let/fn-name-gen': [FAIL],
-  'language/statements/variable/fn-name-arrow': [FAIL],
-  'language/statements/variable/fn-name-class': [FAIL],
-  'language/statements/variable/fn-name-cover': [FAIL],
-  'language/statements/variable/fn-name-fn': [FAIL],
-  'language/statements/variable/fn-name-gen': [FAIL],
 
   # https://code.google.com/p/v8/issues/detail?id=4251
   'language/expressions/postfix-increment/S11.3.1_A5_T1': [FAIL],
@@ -273,30 +153,6 @@
   # https://code.google.com/p/v8/issues/detail?id=4253
   'language/asi/S7.9_A5.7_T1': [PASS, FAIL_OK],
 
-  # https://code.google.com/p/v8/issues/detail?id=3761
-  'language/expressions/object/method-definition/generator-name-prop-symbol': [FAIL],
-  'language/expressions/object/method-definition/name-name-prop-symbol': [FAIL],
-
-  # https://code.google.com/p/v8/issues/detail?id=2952
-  'built-ins/RegExp/prototype/exec/u-lastindex-adv': [FAIL],
-  'built-ins/RegExp/prototype/exec/u-captured-value': [FAIL],
-  'built-ins/RegExp/prototype/exec/u-lastindex-value': [FAIL],
-  'built-ins/RegExp/prototype/test/u-captured-value': [FAIL],
-  'built-ins/RegExp/prototype/test/u-lastindex-adv': [FAIL],
-  'built-ins/RegExp/prototype/test/u-lastindex-value': [FAIL],
-  'built-ins/RegExp/prototype/unicode/this-regexp': [FAIL],
-  'built-ins/RegExp/unicode_identity_escape': [FAIL],
-  'language/literals/regexp/u-unicode-esc': [FAIL],
-  'language/literals/regexp/u-surrogate-pairs': [FAIL],
-  'language/literals/regexp/u-case-mapping': [FAIL],
-  'language/literals/regexp/u-astral': [FAIL],
-  'built-ins/RegExp/valid-flags-y': [FAIL],
-  'built-ins/RegExp/prototype/unicode/length': [FAIL],
-  'built-ins/RegExp/prototype/unicode/name': [FAIL],
-  'built-ins/RegExp/prototype/unicode/prop-desc': [FAIL],
-  'built-ins/RegExp/prototype/unicode/this-invald-obj': [FAIL],
-  'built-ins/RegExp/prototype/unicode/this-non-obj': [FAIL],
-
    # https://code.google.com/p/v8/issues/detail?id=4602
   'built-ins/RegExp/prototype/exec/get-sticky-coerce': [FAIL],
   'built-ins/RegExp/prototype/exec/get-sticky-err': [FAIL],
@@ -311,36 +167,19 @@
   # happens to be thrown for some other reason (e.g,
   # built-ins/RegExp/prototype/Symbol.match/builtin-failure-set-lastindex-err)
   'built-ins/RegExp/prototype/Symbol.match/*': [SKIP],
-  'built-ins/Symbol/match/prop-desc': [FAIL],
   'built-ins/String/prototype/endsWith/return-abrupt-from-searchstring-regexp-test': [FAIL],
   'built-ins/String/prototype/includes/return-abrupt-from-searchstring-regexp-test': [FAIL],
   'built-ins/String/prototype/startsWith/return-abrupt-from-searchstring-regexp-test': [FAIL],
-  'built-ins/String/prototype/match/cstm-matcher-get-err': [FAIL],
   'built-ins/String/prototype/match/invoke-builtin-match': [FAIL],
-  'built-ins/String/prototype/match/cstm-matcher-invocation': [FAIL],
 
   # https://code.google.com/p/v8/issues/detail?id=4343
   'built-ins/RegExp/prototype/Symbol.replace/*': [SKIP],
-  'built-ins/Symbol/replace/prop-desc': [FAIL],
-  'built-ins/String/prototype/replace/cstm-replace-get-err': [FAIL],
-  'built-ins/String/prototype/replace/cstm-replace-invocation': [FAIL],
 
   # https://code.google.com/p/v8/issues/detail?id=4344
   'built-ins/RegExp/prototype/Symbol.search/*': [SKIP],
-  'built-ins/Symbol/search/prop-desc': [FAIL],
-  'built-ins/String/prototype/search/cstm-search-get-err': [FAIL],
-  'built-ins/String/prototype/search/invoke-builtin-search-searcher-undef': [FAIL],
-  'built-ins/String/prototype/search/cstm-search-invocation': [FAIL],
-  'built-ins/String/prototype/search/invoke-builtin-search': [FAIL],
 
   # https://code.google.com/p/v8/issues/detail?id=4345
   'built-ins/RegExp/prototype/Symbol.split/*': [SKIP],
-  'built-ins/Symbol/split/prop-desc': [FAIL],
-  'built-ins/String/prototype/split/cstm-split-invocation': [FAIL],
-  'built-ins/String/prototype/split/cstm-split-get-err': [FAIL],
-
-  # https://code.google.com/p/v8/issues/detail?id=4346
-  'built-ins/RegExp/prototype/flags/u': [FAIL],
 
   # https://code.google.com/p/v8/issues/detail?id=4360
   'intl402/Collator/10.1.1_1': [FAIL],
@@ -350,13 +189,6 @@
   # https://code.google.com/p/v8/issues/detail?id=4361
   'intl402/Collator/10.1.1_a': [FAIL],
 
-  # https://code.google.com/p/v8/issues/detail?id=4447
-  'built-ins/Function/prototype/Symbol.hasInstance/*': [SKIP],
-  'built-ins/Symbol/hasInstance/prop-desc': [FAIL],
-  'language/expressions/instanceof/symbol-hasinstance-get-err': [FAIL],
-  'language/expressions/instanceof/symbol-hasinstance-invocation': [FAIL],
-  'language/expressions/instanceof/symbol-hasinstance-to-boolean': [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],
@@ -381,11 +213,7 @@
   'built-ins/ArrayBuffer/length-is-absent': [FAIL],
   'built-ins/ArrayBuffer/length-is-not-number': [FAIL],
   'built-ins/ArrayBuffer/positive-integer-length': [FAIL],
-
-  # https://bugs.chromium.org/p/v8/issues/detail?id=4630
-  'language/statements/generators/invoke-as-constructor': [FAIL],
-  'language/expressions/generators/invoke-as-constructor': [FAIL],
-  'language/expressions/object/method-definition/generator-invoke-ctor': [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],
@@ -409,8 +237,20 @@
   '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=4639
-  'built-ins/ArrayBuffer/allocation-limit': [SKIP],
+  # 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://bugs.chromium.org/p/v8/issues/detail?id=4663
+  'built-ins/object/entries/*': [SKIP],
+  'built-ins/object/values/*': [SKIP],
+  'built-ins/Object/entries/*': [SKIP],
+  'built-ins/Object/values/*': [SKIP],
 
   # https://code.google.com/p/chromium/issues/detail?id=581577
   'built-ins/RegExp/prototype/source/15.10.7.1-1': [FAIL],
@@ -496,8 +336,9 @@
   'built-ins/Array/prototype/indexOf/15.4.4.14-5-9': [FAIL],
   'built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-9': [FAIL],
 
-  # https://github.com/tc39/test262/issues/436
-  'built-ins/RegExp/call_with_regexp_match_falsy': [FAIL],
+  # https://github.com/tc39/test262/issues/489
+  # Test will pass in 0 or -GMT, but fail in +GMT
+  'language/statements/class/subclass/builtin-objects/Date/regular-subclassing': [PASS, FAIL_OK],
 
   ############################ SKIPPED TESTS #############################
 
@@ -544,12 +385,18 @@
   'intl402/NumberFormat/prototype/format/11.3.2_TRP': [SKIP],
 }],  # system == macos
 
-['no_i18n == True and mode == debug', {
+['no_i18n == True', {
+  # Unicode canonicalization is not available with i18n turned off.
+  'built-ins/String/prototype/localeCompare/15.5.4.9_CE': [SKIP],
+
+  # Unicode regexp case mapping is not available with i18n turned off.
+  'language/literals/regexp/u-case-mapping': [SKIP],
+
   # BUG(v8:4437).
   '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 and mode == debug
+}],  # no_i18n == True
 
 
 ['arch == arm or arch == mipsel or arch == mips or arch == arm64 or arch == mips64 or arch == mips64el', {
@@ -571,7 +418,13 @@
   # BUG(v8:4653): Test262 tests which rely on quit() are not compatible with
   # asan's --omit-quit flag.
   'built-ins/Promise/prototype/then/deferred-is-resolved-value': [SKIP],
-}],
+}],  # asan == True
+
+['asan == True or msan == True or tsan == True', {
+  # 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],
+}],  # asan == True or msan == True or tsan == True
 
 ['ignition == True', {
   'annexB/B.2.3.*': [SKIP],
@@ -579,48 +432,37 @@
   'built-ins/Array/prototype/reduceRight/*': [SKIP],
   'built-ins/GeneratorFunction/*': [SKIP],
   'built-ins/GeneratorPrototype/*': [SKIP],
-  'built-ins/Map/*': [SKIP],
-  'built-ins/MapIteratorPrototype/*': [SKIP],
-  'built-ins/Promise/prototype/then/capability-executor-called-twice': [SKIP],
   'built-ins/Promise/prototype/then/capability-executor-not-callable': [SKIP],
-  'built-ins/Promise/prototype/then/deferred-is-resolved-value': [SKIP],
-  'built-ins/Proxy/has/*': [SKIP],
   'built-ins/Reflect/enumerate/*': [SKIP],
-  'built-ins/Set/*': [SKIP],
-  'built-ins/SetIteratorPrototype/*': [SKIP],
-  'built-ins/WeakMap/*': [SKIP],
-  'built-ins/WeakSet/*': [SKIP],
   'language/computed-property-names/class/*': [SKIP],
   'language/computed-property-names/to-name-side-effects/*': [SKIP],
   'language/directive-prologue/*': [SKIP],
   'language/expressions/arrow-function/*': [SKIP],
   'language/expressions/assignment/destructuring/*': [SKIP],
-  'language/expressions/class/*': [SKIP],
+  'language/expressions/class/subclass/builtin-objects/GeneratorFunction/*': [SKIP],
   'language/expressions/generators/*': [SKIP],
+  'language/expressions/instanceof/primitive-prototype-with-object': [SKIP],
+  'language/expressions/instanceof/prototype-getter-with-object-throws': [SKIP],
+  'language/expressions/instanceof/prototype-getter-with-object': [SKIP],
   'language/expressions/object/method-definition/yield*': [SKIP],
   'language/expressions/object/method-definition/generator*': [SKIP],
-  'language/expressions/object/prop-def-id-eval-error-2': [SKIP],
   'language/expressions/yield/*': [SKIP],
-  'language/function-code/*': [SKIP],
-  'language/statements/class/*': [SKIP],
-  'language/statements/const/*': [SKIP],
-  'language/statements/for-in/const*': [SKIP],
-  'language/statements/for-in/let*': [SKIP],
-  'language/statements/for-of/*': [SKIP],
+  'language/statements/class/definition/methods-gen-no-yield': [SKIP],
+  'language/statements/class/definition/methods-gen-return': [SKIP],
+  'language/statements/class/definition/methods-gen-yield-as-expression-with-rhs': [SKIP],
+  'language/statements/class/definition/methods-gen-yield-as-generator-method-binding-identifier': [SKIP],
+  'language/statements/class/definition/methods-gen-yield-as-literal-property-name': [SKIP],
+  'language/statements/class/definition/methods-gen-yield-as-property-name': [SKIP],
+  'language/statements/class/definition/methods-gen-yield-as-statement': [SKIP],
+  'language/statements/class/definition/methods-gen-yield-as-expression-without-rhs': [SKIP],
+  'language/statements/class/definition/methods-gen-yield-as-yield-operand': [SKIP],
+  'language/statements/class/definition/methods-gen-yield-newline': [SKIP],
+  'language/statements/class/definition/methods-gen-yield-star-before-newline': [SKIP],
+  'language/statements/class/subclass/builtin-objects/GeneratorFunction/*': [SKIP],
   'language/statements/generators/*': [SKIP],
-  'language/statements/try/*': [SKIP],
-  'language/statements/with/*': [SKIP],
 
   'built-ins/Array/prototype/concat/Array.prototype.concat_non-array': [SKIP],
-  'built-ins/Array/prototype/join/S15.4.4.5_A3.1_T1': [SKIP],
-  'built-ins/Array/prototype/join/S15.4.4.5_A3.1_T2': [SKIP],
-  'built-ins/Array/prototype/toString/S15.4.4.2_A1_T2': [SKIP],
-  'built-ins/Array/prototype/toString/S15.4.4.2_A1_T3': [SKIP],
-  'built-ins/Array/prototype/toString/S15.4.4.2_A1_T4': [SKIP],
-  'built-ins/Date/15.9.1.15-1': [SKIP],
   'built-ins/Date/prototype/toISOString/15.9.5.43-0-13': [SKIP],
-  'built-ins/JSON/stringify/*': [SKIP],
-  'built-ins/Object/defineProperty/15.2.3.6-4-625gs': [SKIP],
   'built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A12': [SKIP],
   'built-ins/Object/prototype/isPrototypeOf/S15.2.4.6_A12': [SKIP],
   'built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A12': [SKIP],
@@ -631,10 +473,8 @@
   'built-ins/Object/prototype/valueOf/S15.2.4.4_A12': [SKIP],
   'built-ins/Object/prototype/valueOf/S15.2.4.4_A14': [SKIP],
   'built-ins/Object/prototype/valueOf/S15.2.4.4_A15': [SKIP],
-  'built-ins/Promise/all/ctx-ctor': [SKIP],
-  'built-ins/Promise/race/ctx-ctor': [SKIP],
-  'built-ins/Promise/reject/ctx-ctor': [SKIP],
-  'built-ins/Promise/resolve/ctx-ctor': [SKIP],
+  'built-ins/Promise/all/S25.4.4.1_A4.1_T1': [SKIP],
+  'built-ins/Promise/prototype/then/on-rejected-throw': [SKIP],
   'built-ins/Promise/reject/S25.4.4.4_A3.1_T1': [SKIP],
   'built-ins/String/prototype/codePointAt/this-is-undefined-throws': [SKIP],
   'built-ins/String/prototype/concat/S15.5.4.6_A2': [SKIP],
@@ -643,84 +483,138 @@
   'built-ins/String/prototype/repeat/this-is-undefined-throws': [SKIP],
   'built-ins/String/prototype/startsWith/this-is-undefined-throws': [SKIP],
   'built-ins/String/prototype/trim/15.5.4.20-1-1': [SKIP],
-  'built-ins/String/S15.5.5.1_A4_T1': [SKIP],
   'language/block-scope/leave/nested-block-let-declaration-only-shadows-outer-parameter-value-1': [SKIP],
   'language/block-scope/leave/nested-block-let-declaration-only-shadows-outer-parameter-value-2': [SKIP],
   'language/block-scope/leave/verify-context-in-labelled-block': [SKIP],
   'language/block-scope/leave/x-after-break-to-label': [SKIP],
-  'language/computed-property-names/object/accessor/getter-super': [SKIP],
-  'language/computed-property-names/object/accessor/setter-super': [SKIP],
-  'language/computed-property-names/object/method/super': [SKIP],
   'language/default-parameters/class-definitions': [SKIP],
   'language/default-parameters/generators': [SKIP],
-  'language/default-parameters/param-ref-uninitialized': [SKIP],
-  'language/expressions/delete/11.4.1-4.a-5': [SKIP],
-  'language/expressions/delete/11.4.1-4.a-6': [SKIP],
   'language/expressions/object/method-definition/name-prop-name-yield-expr': [SKIP],
-  'language/expressions/object/method-definition/name-super-prop-param': [SKIP],
-  'language/expressions/object/method-definition/name-super-prop-body': [SKIP],
-  'language/expressions/object/prop-def-id-eval-error': [SKIP],
   'language/expressions/tagged-template/call-expression-context-no-strict': [SKIP],
   'language/expressions/tagged-template/call-expression-context-strict': [SKIP],
   'language/expressions/template-literal/evaluation-order': [SKIP],
-  'language/expressions/this/11.1.1-1gs': [SKIP],
-  'language/identifier-resolution/S10.2.2_A1_T5': [SKIP],
-  'language/identifier-resolution/S10.2.2_A1_T6': [SKIP],
-  'language/identifier-resolution/S10.2.2_A1_T7': [SKIP],
-  'language/identifier-resolution/S10.2.2_A1_T8': [SKIP],
-  'language/identifier-resolution/S10.2.2_A1_T9': [SKIP],
+  'language/statements/for-of/body-dstr-assign': [SKIP],
+  'language/statements/for-of/break': [SKIP],
+  'language/statements/for-of/break-from-catch': [SKIP],
+  'language/statements/for-of/break-from-finally': [SKIP],
+  'language/statements/for-of/break-from-try': [SKIP],
+  'language/statements/for-of/break-label': [SKIP],
+  'language/statements/for-of/break-label-from-catch': [SKIP],
+  'language/statements/for-of/break-label-from-finally': [SKIP],
+  'language/statements/for-of/break-label-from-try': [SKIP],
+  'language/statements/for-of/continue': [SKIP],
+  'language/statements/for-of/continue-from-catch': [SKIP],
+  'language/statements/for-of/continue-from-finally': [SKIP],
+  'language/statements/for-of/continue-from-try': [SKIP],
+  'language/statements/for-of/continue-label': [SKIP],
+  'language/statements/for-of/continue-label-from-catch': [SKIP],
+  'language/statements/for-of/continue-label-from-finally': [SKIP],
+  'language/statements/for-of/continue-label-from-try': [SKIP],
+  'language/statements/for-of/generator': [SKIP],
+  'language/statements/for-of/generator-next-error': [SKIP],
+  'language/statements/for-of/nested': [SKIP],
+  'language/statements/for-of/return': [SKIP],
+  'language/statements/for-of/return-from-catch': [SKIP],
+  'language/statements/for-of/return-from-finally': [SKIP],
+  'language/statements/for-of/return-from-try': [SKIP],
+  'language/statements/for-of/throw': [SKIP],
+  'language/statements/for-of/throw-from-catch': [SKIP],
+  'language/statements/for-of/throw-from-finally': [SKIP],
+  'language/statements/for-of/yield': [SKIP],
+  'language/statements/for-of/yield-from-catch': [SKIP],
+  'language/statements/for-of/yield-from-finally': [SKIP],
+  'language/statements/for-of/yield-from-try': [SKIP],
+  'language/statements/for-of/yield-star': [SKIP],
+  'language/statements/for-of/yield-star-from-catch': [SKIP],
+  'language/statements/for-of/yield-star-from-finally': [SKIP],
+  'language/statements/for-of/yield-star-from-try': [SKIP],
   'language/object-literal/concise-generator': [SKIP],
-  'language/object-literal/getter': [SKIP],
-  'language/object-literal/method': [SKIP],
-  'language/object-literal/setter': [SKIP],
-  'language/rest-parameters/arrow-function': [SKIP],
-  'language/rest-parameters/expected-argument-count': [SKIP],
-  'language/rest-parameters/no-alias-arguments': [SKIP],
-  'language/rest-parameters/rest-index': [SKIP],
-  'language/rest-parameters/rest-parameters-apply': [SKIP],
-  'language/rest-parameters/rest-parameters-call': [SKIP],
-  'language/rest-parameters/rest-parameters-produce-an-array': [SKIP],
-  'language/rest-parameters/with-new-target': [SKIP],
   'language/statements/do-while/S12.6.1_A4_T5': [SKIP],
-  'language/statements/function/S13.2.2_A18_T2': [SKIP],
-  'language/statements/function/S13.2.2_A19_T1': [SKIP],
-  'language/statements/function/S13.2.2_A19_T2': [SKIP],
-  'language/statements/function/S13.2.2_A19_T3': [SKIP],
-  'language/statements/function/S13.2.2_A19_T4': [SKIP],
-  'language/statements/function/S13.2.2_A19_T5': [SKIP],
-  'language/statements/function/S13.2.2_A19_T6': [SKIP],
-  'language/statements/function/S13.2.2_A19_T7': [SKIP],
-  'language/statements/function/S13.2.2_A19_T8': [SKIP],
-  'language/statements/function/S13.2.2_A18_T1': [SKIP],
-  'language/statements/function/S13.2.2_A17_T2': [SKIP],
-  'language/statements/function/S13.2.2_A17_T3': [SKIP],
-  'language/statements/let/block-local-closure-get-before-initialization': [SKIP],
-  'language/statements/let/block-local-closure-set-before-initialization': [SKIP],
-  'language/statements/let/block-local-use-before-initialization-in-declaration-statement': [SKIP],
-  'language/statements/let/block-local-use-before-initialization-in-prior-statement': [SKIP],
-  'language/statements/let/function-local-closure-get-before-initialization': [SKIP],
-  'language/statements/let/function-local-closure-set-before-initialization': [SKIP],
-  'language/statements/let/function-local-use-before-initialization-in-declaration-statement': [SKIP],
-  'language/statements/let/function-local-use-before-initialization-in-prior-statement': [SKIP],
-  'language/statements/let/global-closure-get-before-initialization': [SKIP],
-  'language/statements/let/global-closure-set-before-initialization': [SKIP],
-  'language/statements/let/global-use-before-initialization-in-declaration-statement': [SKIP],
-  'language/statements/let/global-use-before-initialization-in-prior-statement': [SKIP],
   'language/statements/while/S12.6.2_A4_T5': [SKIP],
+  'language/expressions/instanceof/symbol-hasinstance-not-callable': [SKIP],
 
 }],  # ignition == True
 
 ['ignition == True and (arch == arm or arch == arm64)', {
+  'built-ins/Promise/all/ctx-ctor': [SKIP],
+  'built-ins/Promise/race/ctx-ctor': [SKIP],
   'built-ins/decodeURI/S15.1.3.1_A1.12_T3': [SKIP],
   'built-ins/decodeURIComponent/S15.1.3.2_A1.10_T1': [SKIP],
   'built-ins/decodeURIComponent/S15.1.3.2_A1.11_T2': [SKIP],
   'built-ins/decodeURIComponent/S15.1.3.2_A1.12_T2': [SKIP],
   'built-ins/decodeURIComponent/S15.1.3.2_A1.12_T3': [SKIP],
   'intl402/9.2.2': [SKIP],
+  'language/statements/class/arguments/default-constructor': [SKIP],
+  'language/statements/class/definition/constructor-strict-by-default': [SKIP],
+  'language/statements/class/definition/fn-name-accessor-get': [SKIP],
+  'language/statements/class/definition/fn-name-accessor-set': [SKIP],
+  'language/statements/class/definition/fn-name-gen-method': [SKIP],
+  'language/statements/class/definition/fn-name-method': [SKIP],
+  'language/statements/class/definition/methods-restricted-properties': [SKIP],
+  'language/statements/class/definition/prototype-getter': [SKIP],
+  'language/statements/class/definition/prototype-wiring': [SKIP],
+  'language/statements/class/definition/this-access-restriction': [SKIP],
+  'language/statements/class/definition/this-access-restriction-2': [SKIP],
+  'language/statements/class/definition/this-check-ordering': [SKIP],
+  'language/statements/class/name': [SKIP],
+  'language/statements/class/restricted-properties': [SKIP],
+  'language/statements/class/subclass/binding': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Array/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/ArrayBuffer/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Boolean/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/DataView/regular-subclassing': [SKIP],
+  'language/statements/class/subclass/builtin-objects/DataView/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Date/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Error/regular-subclassing': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Error/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Function/instance-length': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Function/instance-name': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Function/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Map/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/EvalError-name': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/EvalError-super': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/RangeError-name': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/RangeError-super': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/ReferenceError-name': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/ReferenceError-super': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/SyntaxError-name': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/SyntaxError-super': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/TypeError-name': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/TypeError-super': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/URIError-name': [SKIP],
+  'language/statements/class/subclass/builtin-objects/NativeError/URIError-super': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Number/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Object/constructor-return-undefined-throws': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Object/constructor-returns-non-object': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Promise/regular-subclassing': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Promise/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/RegExp/lastIndex': [SKIP],
+  'language/statements/class/subclass/builtin-objects/RegExp/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Set/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/String/length': [SKIP],
+  'language/statements/class/subclass/builtin-objects/String/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/Symbol/new-symbol-with-super-throws': [SKIP],
+  'language/statements/class/subclass/builtin-objects/WeakMap/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/builtin-objects/WeakSet/super-must-be-called': [SKIP],
+  'language/statements/class/subclass/class-definition-null-proto-missing-return-override': [SKIP],
+  'language/statements/class/subclass/default-constructor': [SKIP],
+  'language/statements/class/subclass/default-constructor-2': [SKIP],
+  'language/statements/class/subclass/derived-class-return-override-with-boolean': [SKIP],
+  'language/statements/class/subclass/derived-class-return-override-with-null': [SKIP],
+  'language/statements/class/subclass/derived-class-return-override-with-number': [SKIP],
+  'language/statements/class/subclass/derived-class-return-override-with-string': [SKIP],
+  'language/statements/class/subclass/derived-class-return-override-with-symbol': [SKIP],
+  'language/statements/const/fn-name-arrow': [SKIP],
+  'language/statements/const/fn-name-class': [SKIP],
+  'language/statements/const/fn-name-cover': [SKIP],
+  'language/statements/const/fn-name-fn': [SKIP],
+  'language/statements/const/fn-name-gen': [SKIP],
   'language/statements/let/fn-name-arrow': [SKIP],
+  'language/statements/let/fn-name-class': [SKIP],
   'language/statements/let/fn-name-cover': [SKIP],
   'language/statements/let/fn-name-fn': [SKIP],
   'language/statements/let/fn-name-gen': [SKIP],
+  'test-api/Regress470113': [SKIP],
 }],  # ignition == True and (arch == arm or arch == arm64)
 
 ]
diff --git a/test/test262/testcfg.py b/test/test262/testcfg.py
index f222e1e..b5ad309 100644
--- a/test/test262/testcfg.py
+++ b/test/test262/testcfg.py
@@ -39,6 +39,8 @@
 from testrunner.local import utils
 from testrunner.objects import testcase
 
+ARCHIVE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data.tar")
+
 TEST_262_HARNESS_FILES = ["sta.js", "assert.js"]
 
 TEST_262_SUITE_PATH = ["data", "test"]
@@ -199,6 +201,11 @@
       for f in archive_files:
         os.remove(os.path.join(self.root, f))
 
+    print "Extracting archive..."
+    tar = tarfile.open(ARCHIVE)
+    tar.extractall(path=os.path.dirname(ARCHIVE))
+    tar.close()
+
 
 def GetSuite(name, root):
   return Test262TestSuite(name, root)
diff --git a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
index 62abeda..72cfc51 100644
--- a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
+++ b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
@@ -1584,7 +1584,7 @@
   StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
                   MachineType::Float32());
   m.Return(
-      m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
+      m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
   Stream const s = m.Build();
   ASSERT_EQ(1U, s.size());
   EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
@@ -1667,7 +1667,7 @@
   StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
                   MachineType::Float64());
   m.Return(
-      m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
+      m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
   Stream const s = m.Build();
   ASSERT_EQ(1U, s.size());
   EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
@@ -2544,8 +2544,28 @@
 }
 
 
+TEST_F(InstructionSelectorTest, Word32ShlWord32SarForSbfx) {
+  TRACED_FORRANGE(int32_t, shl, 1, 31) {
+    TRACED_FORRANGE(int32_t, sar, shl, 31) {
+      if ((shl == sar) && (sar == 16)) continue;  // Sxth.
+      if ((shl == sar) && (sar == 24)) continue;  // Sxtb.
+      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+      m.Return(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(shl)),
+                           m.Int32Constant(sar)));
+      Stream s = m.Build(ARMv7);
+      ASSERT_EQ(1U, s.size());
+      EXPECT_EQ(kArmSbfx, s[0]->arch_opcode());
+      ASSERT_EQ(3U, s[0]->InputCount());
+      EXPECT_EQ(sar - shl, s.ToInt32(s[0]->InputAt(1)));
+      EXPECT_EQ(32 - sar, s.ToInt32(s[0]->InputAt(2)));
+    }
+  }
+}
+
+
 TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
-  TRACED_FORRANGE(int32_t, width, 1, 32) {
+  TRACED_FORRANGE(int32_t, width, 9, 23) {
+    if (width == 16) continue;  // Uxth.
     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
     m.Return(m.Word32And(m.Parameter(0),
                          m.Int32Constant(0xffffffffu >> (32 - width))));
@@ -2556,7 +2576,8 @@
     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
     EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
   }
-  TRACED_FORRANGE(int32_t, width, 1, 32) {
+  TRACED_FORRANGE(int32_t, width, 9, 23) {
+    if (width == 16) continue;  // Uxth.
     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
     m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
                          m.Parameter(0)));
@@ -2572,7 +2593,7 @@
 
 TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
   TRACED_FORRANGE(int32_t, lsb, 0, 31) {
-    TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) {
+    TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
       m.Return(m.Word32And(
           m.Parameter(0),
@@ -2589,7 +2610,7 @@
     }
   }
   TRACED_FORRANGE(int32_t, lsb, 0, 31) {
-    TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) {
+    TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
       m.Return(
           m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
@@ -2828,8 +2849,11 @@
 
 
 TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
-  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
+  TRACED_FORRANGE(int32_t, lsb, 1, 31) {
     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
+      if (((width == 8) || (width == 16)) &&
+          ((lsb == 8) || (lsb == 16) || (lsb == 24)))
+        continue;  // Uxtb/h ror.
       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
       m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
                            m.Int32Constant(0xffffffffu >> (32 - width))));
@@ -2841,8 +2865,11 @@
       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
     }
   }
-  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
+  TRACED_FORRANGE(int32_t, lsb, 1, 31) {
     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
+      if (((width == 8) || (width == 16)) &&
+          ((lsb == 8) || (lsb == 16) || (lsb == 24)))
+        continue;  // Uxtb/h ror.
       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
       m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
                            m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
@@ -2857,6 +2884,62 @@
 }
 
 
+TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xff) {
+  TRACED_FORRANGE(int32_t, shr, 1, 3) {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+    Node* const p0 = m.Parameter(0);
+    Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
+                                m.Int32Constant(0xff));
+    m.Return(r);
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
+    ASSERT_EQ(2U, s[0]->InputCount());
+    EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
+  }
+  TRACED_FORRANGE(int32_t, shr, 1, 3) {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+    Node* const p0 = m.Parameter(0);
+    Node* const r = m.Word32And(m.Int32Constant(0xff),
+                                m.Word32Shr(p0, m.Int32Constant(shr * 8)));
+    m.Return(r);
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
+    ASSERT_EQ(2U, s[0]->InputCount());
+    EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
+  }
+}
+
+
+TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xffff) {
+  TRACED_FORRANGE(int32_t, shr, 1, 3) {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+    Node* const p0 = m.Parameter(0);
+    Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
+                                m.Int32Constant(0xffff));
+    m.Return(r);
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
+    ASSERT_EQ(2U, s[0]->InputCount());
+    EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
+  }
+  TRACED_FORRANGE(int32_t, shr, 1, 3) {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+    Node* const p0 = m.Parameter(0);
+    Node* const r = m.Word32And(m.Int32Constant(0xffff),
+                                m.Word32Shr(p0, m.Int32Constant(shr * 8)));
+    m.Return(r);
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
+    ASSERT_EQ(2U, s[0]->InputCount());
+    EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
+  }
+}
+
+
 TEST_F(InstructionSelectorTest, Word32Clz) {
   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
   Node* const p0 = m.Parameter(0);
diff --git a/test/unittests/compiler/escape-analysis-unittest.cc b/test/unittests/compiler/escape-analysis-unittest.cc
index b088367..d5e12ba 100644
--- a/test/unittests/compiler/escape-analysis-unittest.cc
+++ b/test/unittests/compiler/escape-analysis-unittest.cc
@@ -9,7 +9,7 @@
 #include "src/compiler/js-graph.h"
 #include "src/compiler/node-properties.h"
 #include "src/compiler/simplified-operator.h"
-#include "src/types-inl.h"
+#include "src/types.h"
 #include "src/zone-containers.h"
 #include "test/unittests/compiler/graph-unittest.h"
 
@@ -85,6 +85,20 @@
                                       allocation, value, effect, control);
   }
 
+  Node* StoreElement(const ElementAccess& access, Node* allocation, Node* index,
+                     Node* value, Node* effect = nullptr,
+                     Node* control = nullptr) {
+    if (!effect) {
+      effect = effect_;
+    }
+    if (!control) {
+      control = control_;
+    }
+    return effect_ =
+               graph()->NewNode(simplified()->StoreElement(access), allocation,
+                                index, value, effect, control);
+  }
+
   Node* Load(const FieldAccess& access, Node* from, Node* effect = nullptr,
              Node* control = nullptr) {
     if (!effect) {
@@ -131,12 +145,18 @@
     return control_ = graph()->NewNode(common()->Merge(2), control1, control2);
   }
 
-  FieldAccess AccessAtIndex(int offset) {
+  FieldAccess FieldAccessAtIndex(int offset) {
     FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(),
                           MachineType::AnyTagged()};
     return access;
   }
 
+  ElementAccess MakeElementAccess(int header_size) {
+    ElementAccess access = {kTaggedBase, header_size, Type::Any(),
+                            MachineType::AnyTagged()};
+    return access;
+  }
+
   // ---------------------------------Assertion Helper--------------------------
 
   void ExpectReplacement(Node* node, Node* rep) {
@@ -166,6 +186,7 @@
   SimplifiedOperatorBuilder* simplified() { return &simplified_; }
 
   Node* effect() { return effect_; }
+  Node* control() { return control_; }
 
  private:
   SimplifiedOperatorBuilder simplified_;
@@ -185,9 +206,9 @@
   Node* object1 = Constant(1);
   BeginRegion();
   Node* allocation = Allocate(Constant(kPointerSize));
-  Store(AccessAtIndex(0), allocation, object1);
+  Store(FieldAccessAtIndex(0), allocation, object1);
   Node* finish = FinishRegion(allocation);
-  Node* load = Load(AccessAtIndex(0), finish);
+  Node* load = Load(FieldAccessAtIndex(0), finish);
   Node* result = Return(load);
   EndGraph();
 
@@ -202,13 +223,39 @@
 }
 
 
+TEST_F(EscapeAnalysisTest, StraightNonEscapeNonConstStore) {
+  Node* object1 = Constant(1);
+  Node* object2 = Constant(2);
+  BeginRegion();
+  Node* allocation = Allocate(Constant(kPointerSize));
+  Store(FieldAccessAtIndex(0), allocation, object1);
+  Node* index =
+      graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
+                       object1, object2, control());
+  StoreElement(MakeElementAccess(0), allocation, index, object1);
+  Node* finish = FinishRegion(allocation);
+  Node* load = Load(FieldAccessAtIndex(0), finish);
+  Node* result = Return(load);
+  EndGraph();
+
+  Analysis();
+
+  ExpectEscaped(allocation);
+  ExpectReplacement(load, nullptr);
+
+  Transformation();
+
+  ASSERT_EQ(load, NodeProperties::GetValueInput(result, 0));
+}
+
+
 TEST_F(EscapeAnalysisTest, StraightEscape) {
   Node* object1 = Constant(1);
   BeginRegion();
   Node* allocation = Allocate(Constant(kPointerSize));
-  Store(AccessAtIndex(0), allocation, object1);
+  Store(FieldAccessAtIndex(0), allocation, object1);
   Node* finish = FinishRegion(allocation);
-  Node* load = Load(AccessAtIndex(0), finish);
+  Node* load = Load(FieldAccessAtIndex(0), finish);
   Node* result = Return(allocation);
   EndGraph();
   graph()->end()->AppendInput(zone(), load);
@@ -229,15 +276,15 @@
 
   BeginRegion();
   Node* allocation1 = Allocate(Constant(kPointerSize));
-  Store(AccessAtIndex(0), allocation1, object1);
+  Store(FieldAccessAtIndex(0), allocation1, object1);
   Node* finish1 = FinishRegion(allocation1);
 
   BeginRegion();
   Node* allocation2 = Allocate(Constant(kPointerSize));
-  Store(AccessAtIndex(0), allocation2, finish1);
+  Store(FieldAccessAtIndex(0), allocation2, finish1);
   Node* finish2 = FinishRegion(allocation2);
 
-  Node* load = Load(AccessAtIndex(0), finish2);
+  Node* load = Load(FieldAccessAtIndex(0), finish2);
   Node* result = Return(load);
   EndGraph();
   Analysis();
@@ -257,16 +304,18 @@
   Node* object2 = Constant(2);
   BeginRegion();
   Node* allocation = Allocate(Constant(kPointerSize));
-  Store(AccessAtIndex(0), allocation, object1);
+  Store(FieldAccessAtIndex(0), allocation, object1);
   Node* finish = FinishRegion(allocation);
   Branch();
   Node* ifFalse = IfFalse();
   Node* ifTrue = IfTrue();
-  Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish, ifFalse);
-  Node* effect2 = Store(AccessAtIndex(0), allocation, object2, finish, ifTrue);
+  Node* effect1 =
+      Store(FieldAccessAtIndex(0), allocation, object1, finish, ifFalse);
+  Node* effect2 =
+      Store(FieldAccessAtIndex(0), allocation, object2, finish, ifTrue);
   Node* merge = Merge2(ifFalse, ifTrue);
   Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge);
-  Node* load = Load(AccessAtIndex(0), finish, phi, merge);
+  Node* load = Load(FieldAccessAtIndex(0), finish, phi, merge);
   Node* result = Return(load, phi);
   EndGraph();
   graph()->end()->AppendInput(zone(), result);
@@ -283,14 +332,81 @@
 }
 
 
+TEST_F(EscapeAnalysisTest, BranchEscapeOne) {
+  Node* object1 = Constant(1);
+  Node* object2 = Constant(2);
+  Node* index = graph()->NewNode(common()->Parameter(0), start());
+  BeginRegion();
+  Node* allocation = Allocate(Constant(kPointerSize));
+  Store(FieldAccessAtIndex(0), allocation, object1);
+  Node* finish = FinishRegion(allocation);
+  Branch();
+  Node* ifFalse = IfFalse();
+  Node* ifTrue = IfTrue();
+  Node* effect1 =
+      Store(FieldAccessAtIndex(0), allocation, object1, finish, ifFalse);
+  Node* effect2 = StoreElement(MakeElementAccess(0), allocation, index, object2,
+                               finish, ifTrue);
+  Node* merge = Merge2(ifFalse, ifTrue);
+  Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge);
+  Node* load = Load(FieldAccessAtIndex(0), finish, phi, merge);
+  Node* result = Return(load, phi);
+  EndGraph();
+
+  Analysis();
+
+  ExpectEscaped(allocation);
+  ExpectReplacement(load, nullptr);
+
+  Transformation();
+
+  ASSERT_EQ(load, NodeProperties::GetValueInput(result, 0));
+}
+
+
+TEST_F(EscapeAnalysisTest, BranchEscapeThroughStore) {
+  Node* object1 = Constant(1);
+  Node* object2 = Constant(2);
+  BeginRegion();
+  Node* allocation = Allocate(Constant(kPointerSize));
+  Store(FieldAccessAtIndex(0), allocation, object1);
+  FinishRegion(allocation);
+  BeginRegion();
+  Node* allocation2 = Allocate(Constant(kPointerSize));
+  Store(FieldAccessAtIndex(0), allocation, object2);
+  Node* finish2 = FinishRegion(allocation2);
+  Branch();
+  Node* ifFalse = IfFalse();
+  Node* ifTrue = IfTrue();
+  Node* effect1 =
+      Store(FieldAccessAtIndex(0), allocation, allocation2, finish2, ifFalse);
+  Node* merge = Merge2(ifFalse, ifTrue);
+  Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, finish2, merge);
+  Node* load = Load(FieldAccessAtIndex(0), finish2, phi, merge);
+  Node* result = Return(allocation, phi);
+  EndGraph();
+  graph()->end()->AppendInput(zone(), load);
+
+  Analysis();
+
+  ExpectEscaped(allocation);
+  ExpectEscaped(allocation2);
+  ExpectReplacement(load, nullptr);
+
+  Transformation();
+
+  ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0));
+}
+
+
 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) {
   Node* object1 = Constant(1);
   Node* object2 = Constant(2);
   Node* allocation = Allocate(Constant(kPointerSize));
-  Node* store1 = Store(AccessAtIndex(0), allocation, object1);
-  Node* load1 = Load(AccessAtIndex(0), allocation);
-  Node* store2 = Store(AccessAtIndex(0), allocation, object2);
-  Node* load2 = Load(AccessAtIndex(0), allocation, store1);
+  Node* store1 = Store(FieldAccessAtIndex(0), allocation, object1);
+  Node* load1 = Load(FieldAccessAtIndex(0), allocation);
+  Node* store2 = Store(FieldAccessAtIndex(0), allocation, object2);
+  Node* load2 = Load(FieldAccessAtIndex(0), allocation, store1);
   Node* result = Return(load2);
   EndGraph();
   graph()->end()->AppendInput(zone(), store2);
@@ -312,9 +428,9 @@
   Node* object1 = Constant(1);
   BeginRegion();
   Node* allocation = Allocate(Constant(kPointerSize));
-  Store(AccessAtIndex(0), allocation, object1);
+  Store(FieldAccessAtIndex(0), allocation, object1);
   Node* finish = FinishRegion(allocation);
-  Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish);
+  Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish);
   Branch();
   Node* ifFalse = IfFalse();
   Node* state_values1 = graph()->NewNode(common()->StateValues(1), finish);
@@ -328,7 +444,7 @@
   Node* deopt = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
                                  frame_state, effect1, ifFalse);
   Node* ifTrue = IfTrue();
-  Node* load = Load(AccessAtIndex(0), finish, effect1, ifTrue);
+  Node* load = Load(FieldAccessAtIndex(0), finish, effect1, ifTrue);
   Node* result = Return(load, effect1, ifTrue);
   EndGraph();
   graph()->end()->AppendInput(zone(), deopt);
@@ -351,10 +467,10 @@
   Node* object1 = Constant(1);
   BeginRegion();
   Node* allocation = Allocate(Constant(kPointerSize * 2));
-  Store(AccessAtIndex(0), allocation, object1);
-  Store(AccessAtIndex(kPointerSize), allocation, allocation);
+  Store(FieldAccessAtIndex(0), allocation, object1);
+  Store(FieldAccessAtIndex(kPointerSize), allocation, allocation);
   Node* finish = FinishRegion(allocation);
-  Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish);
+  Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish);
   Branch();
   Node* ifFalse = IfFalse();
   Node* state_values1 = graph()->NewNode(common()->StateValues(1), finish);
@@ -368,7 +484,7 @@
   Node* deopt = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
                                  frame_state, effect1, ifFalse);
   Node* ifTrue = IfTrue();
-  Node* load = Load(AccessAtIndex(0), finish, effect1, ifTrue);
+  Node* load = Load(FieldAccessAtIndex(0), finish, effect1, ifTrue);
   Node* result = Return(load, effect1, ifTrue);
   EndGraph();
   graph()->end()->AppendInput(zone(), deopt);
diff --git a/test/unittests/compiler/instruction-selector-unittest.cc b/test/unittests/compiler/instruction-selector-unittest.cc
index 89c0a65..16030f8 100644
--- a/test/unittests/compiler/instruction-selector-unittest.cc
+++ b/test/unittests/compiler/instruction-selector-unittest.cc
@@ -40,7 +40,7 @@
                                instruction_blocks);
   SourcePositionTable source_position_table(graph());
   InstructionSelector selector(test_->zone(), node_count, &linkage, &sequence,
-                               schedule, &source_position_table,
+                               schedule, &source_position_table, nullptr,
                                source_position_mode, features);
   selector.SelectInstructions();
   if (FLAG_trace_turbo) {
@@ -148,7 +148,7 @@
     int parameter_count, int local_count) {
   return common()->CreateFrameStateFunctionInfo(
       FrameStateType::kJavaScriptFunction, parameter_count, local_count,
-      Handle<SharedFunctionInfo>(), CALL_MAINTAINS_NATIVE_CONTEXT);
+      Handle<SharedFunctionInfo>());
 }
 
 
diff --git a/test/unittests/compiler/instruction-selector-unittest.h b/test/unittests/compiler/instruction-selector-unittest.h
index fc7c144..f1397fa 100644
--- a/test/unittests/compiler/instruction-selector-unittest.h
+++ b/test/unittests/compiler/instruction-selector-unittest.h
@@ -92,7 +92,7 @@
     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type) {
       MachineSignature::Builder builder(zone, 1, 0);
       builder.AddReturn(return_type);
-      return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
+      return MakeSimpleCallDescriptor(zone, builder.Build());
     }
 
     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
@@ -100,7 +100,7 @@
       MachineSignature::Builder builder(zone, 1, 1);
       builder.AddReturn(return_type);
       builder.AddParam(parameter0_type);
-      return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
+      return MakeSimpleCallDescriptor(zone, builder.Build());
     }
 
     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
@@ -110,7 +110,7 @@
       builder.AddReturn(return_type);
       builder.AddParam(parameter0_type);
       builder.AddParam(parameter1_type);
-      return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
+      return MakeSimpleCallDescriptor(zone, builder.Build());
     }
 
     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
@@ -122,11 +122,48 @@
       builder.AddParam(parameter0_type);
       builder.AddParam(parameter1_type);
       builder.AddParam(parameter2_type);
-      return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
+      return MakeSimpleCallDescriptor(zone, builder.Build());
     }
 
    private:
     InstructionSelectorTest* test_;
+
+    // Create a simple call descriptor for testing.
+    CallDescriptor* MakeSimpleCallDescriptor(Zone* zone,
+                                             MachineSignature* msig) {
+      LocationSignature::Builder locations(zone, msig->return_count(),
+                                           msig->parameter_count());
+
+      // Add return location(s).
+      const int return_count = static_cast<int>(msig->return_count());
+      for (int i = 0; i < return_count; i++) {
+        locations.AddReturn(LinkageLocation::ForCallerFrameSlot(-1 - i));
+      }
+
+      // Just put all parameters on the stack.
+      const int parameter_count = static_cast<int>(msig->parameter_count());
+      for (int i = 0; i < parameter_count; i++) {
+        locations.AddParam(LinkageLocation::ForCallerFrameSlot(-1 - i));
+      }
+
+      const RegList kCalleeSaveRegisters = 0;
+      const RegList kCalleeSaveFPRegisters = 0;
+
+      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
+          msig,                          // machine_sig
+          locations.Build(),             // location_sig
+          0,                             // stack_parameter_count
+          Operator::kNoProperties,       // properties
+          kCalleeSaveRegisters,          // callee-saved registers
+          kCalleeSaveFPRegisters,        // callee-saved fp regs
+          CallDescriptor::kNoFlags,      // flags
+          "iselect-test-call");
+    }
   };
 
   class Stream final {
diff --git a/test/unittests/compiler/int64-lowering-unittest.cc b/test/unittests/compiler/int64-lowering-unittest.cc
new file mode 100644
index 0000000..eff6d4a
--- /dev/null
+++ b/test/unittests/compiler/int64-lowering-unittest.cc
@@ -0,0 +1,299 @@
+// Copyright 2016 the V8 project 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/int64-lowering.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/node.h"
+
+#include "src/compiler/node-properties.h"
+
+#include "src/signature.h"
+
+#include "src/wasm/wasm-module.h"
+
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "testing/gmock-support.h"
+
+using testing::AllOf;
+using testing::Capture;
+using testing::CaptureEq;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class Int64LoweringTest : public GraphTest {
+ public:
+  Int64LoweringTest() : GraphTest(), machine_(zone()) {
+    value_[0] = 0x1234567890abcdef;
+    value_[1] = 0x1edcba098765432f;
+    value_[2] = 0x1133557799886644;
+  }
+
+  MachineOperatorBuilder* machine() { return &machine_; }
+
+  void LowerGraph(Node* node, Signature<MachineRepresentation>* signature) {
+    Node* ret = graph()->NewNode(common()->Return(), node, graph()->start(),
+                                 graph()->start());
+    NodeProperties::MergeControlToEnd(graph(), common(), ret);
+
+    Int64Lowering lowering(graph(), machine(), common(), zone(), signature);
+    lowering.LowerGraph();
+  }
+
+  void LowerGraph(Node* node, MachineRepresentation return_type,
+                  MachineRepresentation rep = MachineRepresentation::kWord32,
+                  int num_params = 0) {
+    Signature<MachineRepresentation>::Builder sig_builder(zone(), 1,
+                                                          num_params);
+    sig_builder.AddReturn(return_type);
+    for (int i = 0; i < num_params; i++) {
+      sig_builder.AddParam(rep);
+    }
+    LowerGraph(node, sig_builder.Build());
+  }
+
+  void CompareCallDescriptors(const CallDescriptor* lhs,
+                              const CallDescriptor* rhs) {
+    EXPECT_THAT(lhs->CalleeSavedFPRegisters(), rhs->CalleeSavedFPRegisters());
+    EXPECT_THAT(lhs->CalleeSavedRegisters(), rhs->CalleeSavedRegisters());
+    EXPECT_THAT(lhs->FrameStateCount(), rhs->FrameStateCount());
+    EXPECT_THAT(lhs->InputCount(), rhs->InputCount());
+    for (size_t i = 0; i < lhs->InputCount(); i++) {
+      EXPECT_THAT(lhs->GetInputLocation(i), rhs->GetInputLocation(i));
+      EXPECT_THAT(lhs->GetInputType(i), rhs->GetInputType(i));
+    }
+    EXPECT_THAT(lhs->ReturnCount(), rhs->ReturnCount());
+    for (size_t i = 0; i < lhs->ReturnCount(); i++) {
+      EXPECT_THAT(lhs->GetReturnLocation(i), rhs->GetReturnLocation(i));
+      EXPECT_THAT(lhs->GetReturnType(i), rhs->GetReturnType(i));
+    }
+    EXPECT_THAT(lhs->flags(), rhs->flags());
+    EXPECT_THAT(lhs->kind(), rhs->kind());
+  }
+
+  int64_t value(int i) { return value_[i]; }
+
+  int32_t low_word_value(int i) {
+    return static_cast<int32_t>(value_[i] & 0xffffffff);
+  }
+
+  int32_t high_word_value(int i) {
+    return static_cast<int32_t>(value_[i] >> 32);
+  }
+
+ private:
+  MachineOperatorBuilder machine_;
+  int64_t value_[3];
+};
+
+TEST_F(Int64LoweringTest, Int64Constant) {
+  if (4 != kPointerSize) return;
+
+  LowerGraph(Int64Constant(value(0)), MachineRepresentation::kWord64);
+  EXPECT_THAT(graph()->end()->InputAt(1),
+              IsReturn2(IsInt32Constant(low_word_value(0)),
+                        IsInt32Constant(high_word_value(0)), start(), start()));
+}
+
+TEST_F(Int64LoweringTest, Int64Load) {
+  if (4 != kPointerSize) return;
+
+  int32_t base = 0x1234;
+  int32_t index = 0x5678;
+
+  LowerGraph(graph()->NewNode(machine()->Load(MachineType::Int64()),
+                              Int32Constant(base), Int32Constant(index),
+                              start(), start()),
+             MachineRepresentation::kWord64);
+
+  Capture<Node*> high_word_load;
+  Matcher<Node*> high_word_load_matcher =
+      IsLoad(MachineType::Int32(), IsInt32Constant(base),
+             IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)), start(),
+             start());
+
+  EXPECT_THAT(
+      graph()->end()->InputAt(1),
+      IsReturn2(IsLoad(MachineType::Int32(), IsInt32Constant(base),
+                       IsInt32Constant(index), AllOf(CaptureEq(&high_word_load),
+                                                     high_word_load_matcher),
+                       start()),
+                AllOf(CaptureEq(&high_word_load), high_word_load_matcher),
+                start(), start()));
+}
+
+TEST_F(Int64LoweringTest, Int64Store) {
+  if (4 != kPointerSize) return;
+
+  // We have to build the TF graph explicitly here because Store does not return
+  // a value.
+
+  int32_t base = 1111;
+  int32_t index = 2222;
+  int32_t return_value = 0x5555;
+
+  Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
+  sig_builder.AddReturn(MachineRepresentation::kWord32);
+
+  Node* store = graph()->NewNode(
+      machine()->Store(StoreRepresentation(MachineRepresentation::kWord64,
+                                           WriteBarrierKind::kNoWriteBarrier)),
+      Int32Constant(base), Int32Constant(index), Int64Constant(value(0)),
+      start(), start());
+
+  Node* ret = graph()->NewNode(common()->Return(), Int32Constant(return_value),
+                               store, start());
+
+  NodeProperties::MergeControlToEnd(graph(), common(), ret);
+
+  Int64Lowering lowering(graph(), machine(), common(), zone(),
+                         sig_builder.Build());
+  lowering.LowerGraph();
+
+  const StoreRepresentation rep(MachineRepresentation::kWord32,
+                                kNoWriteBarrier);
+
+  EXPECT_THAT(
+      graph()->end()->InputAt(1),
+      IsReturn(
+          IsInt32Constant(return_value),
+          IsStore(
+              rep, IsInt32Constant(base), IsInt32Constant(index),
+              IsInt32Constant(low_word_value(0)),
+              IsStore(rep, IsInt32Constant(base),
+                      IsInt32Add(IsInt32Constant(index), IsInt32Constant(4)),
+                      IsInt32Constant(high_word_value(0)), start(), start()),
+              start()),
+          start()));
+}
+
+TEST_F(Int64LoweringTest, Int64And) {
+  if (4 != kPointerSize) return;
+
+  LowerGraph(graph()->NewNode(machine()->Word64And(), Int64Constant(value(0)),
+                              Int64Constant(value(1))),
+             MachineRepresentation::kWord64);
+  EXPECT_THAT(graph()->end()->InputAt(1),
+              IsReturn2(IsWord32And(IsInt32Constant(low_word_value(0)),
+                                    IsInt32Constant(low_word_value(1))),
+                        IsWord32And(IsInt32Constant(high_word_value(0)),
+                                    IsInt32Constant(high_word_value(1))),
+                        start(), start()));
+}
+
+TEST_F(Int64LoweringTest, TruncateInt64ToInt32) {
+  if (4 != kPointerSize) return;
+
+  LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(),
+                              Int64Constant(value(0))),
+             MachineRepresentation::kWord32);
+  EXPECT_THAT(graph()->end()->InputAt(1),
+              IsReturn(IsInt32Constant(low_word_value(0)), start(), start()));
+}
+
+TEST_F(Int64LoweringTest, Parameter) {
+  if (4 != kPointerSize) return;
+
+  LowerGraph(Parameter(0), MachineRepresentation::kWord64,
+             MachineRepresentation::kWord64, 1);
+
+  EXPECT_THAT(graph()->end()->InputAt(1),
+              IsReturn2(IsParameter(0), IsParameter(1), start(), start()));
+}
+
+TEST_F(Int64LoweringTest, Parameter2) {
+  if (4 != kPointerSize) return;
+
+  Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 5);
+  sig_builder.AddReturn(MachineRepresentation::kWord32);
+
+  sig_builder.AddParam(MachineRepresentation::kWord32);
+  sig_builder.AddParam(MachineRepresentation::kWord64);
+  sig_builder.AddParam(MachineRepresentation::kFloat64);
+  sig_builder.AddParam(MachineRepresentation::kWord64);
+  sig_builder.AddParam(MachineRepresentation::kWord32);
+
+  int start_parameter = start()->op()->ValueOutputCount();
+  LowerGraph(Parameter(4), sig_builder.Build());
+
+  EXPECT_THAT(graph()->end()->InputAt(1),
+              IsReturn(IsParameter(6), start(), start()));
+  // The parameter of the start node should increase by 2, because we lowered
+  // two parameter nodes.
+  EXPECT_THAT(start()->op()->ValueOutputCount(), start_parameter + 2);
+}
+
+TEST_F(Int64LoweringTest, CallI64Return) {
+  if (4 != kPointerSize) return;
+
+  int32_t function = 0x9999;
+
+  Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
+  sig_builder.AddReturn(MachineRepresentation::kWord64);
+
+  compiler::CallDescriptor* desc =
+      wasm::ModuleEnv::GetWasmCallDescriptor(zone(), sig_builder.Build());
+
+  LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function),
+                              start(), start()),
+             MachineRepresentation::kWord64);
+
+  Capture<Node*> call;
+  Matcher<Node*> call_matcher =
+      IsCall(testing::_, IsInt32Constant(function), start(), start());
+
+  EXPECT_THAT(graph()->end()->InputAt(1),
+              IsReturn2(IsProjection(0, AllOf(CaptureEq(&call), call_matcher)),
+                        IsProjection(1, AllOf(CaptureEq(&call), call_matcher)),
+                        start(), start()));
+
+  CompareCallDescriptors(
+      OpParameter<const CallDescriptor*>(
+          graph()->end()->InputAt(1)->InputAt(0)->InputAt(0)),
+      wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc));
+}
+
+TEST_F(Int64LoweringTest, CallI64Parameter) {
+  if (4 != kPointerSize) return;
+
+  int32_t function = 0x9999;
+
+  Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 3);
+  sig_builder.AddReturn(MachineRepresentation::kWord32);
+  sig_builder.AddParam(MachineRepresentation::kWord64);
+  sig_builder.AddParam(MachineRepresentation::kWord32);
+  sig_builder.AddParam(MachineRepresentation::kWord64);
+
+  compiler::CallDescriptor* desc =
+      wasm::ModuleEnv::GetWasmCallDescriptor(zone(), sig_builder.Build());
+
+  LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function),
+                              Int64Constant(value(0)),
+                              Int32Constant(low_word_value(1)),
+                              Int64Constant(value(2)), start(), start()),
+             MachineRepresentation::kWord32);
+
+  EXPECT_THAT(
+      graph()->end()->InputAt(1),
+      IsReturn(IsCall(testing::_, IsInt32Constant(function),
+                      IsInt32Constant(low_word_value(0)),
+                      IsInt32Constant(high_word_value(0)),
+                      IsInt32Constant(low_word_value(1)),
+                      IsInt32Constant(low_word_value(2)),
+                      IsInt32Constant(high_word_value(2)), start(), start()),
+               start(), start()));
+
+  CompareCallDescriptors(
+      OpParameter<const CallDescriptor*>(
+          graph()->end()->InputAt(1)->InputAt(0)),
+      wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc));
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/compiler/interpreter-assembler-unittest.h b/test/unittests/compiler/interpreter-assembler-unittest.h
deleted file mode 100644
index 15fa38b..0000000
--- a/test/unittests/compiler/interpreter-assembler-unittest.h
+++ /dev/null
@@ -1,57 +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_UNITTESTS_COMPILER_INTERPRETER_ASSEMBLER_UNITTEST_H_
-#define V8_UNITTESTS_COMPILER_INTERPRETER_ASSEMBLER_UNITTEST_H_
-
-#include "src/compiler/interpreter-assembler.h"
-#include "src/compiler/linkage.h"
-#include "src/compiler/machine-operator.h"
-#include "test/unittests/test-utils.h"
-#include "testing/gmock-support.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-using ::testing::Matcher;
-
-class InterpreterAssemblerTest : public TestWithIsolateAndZone {
- public:
-  InterpreterAssemblerTest() {}
-  ~InterpreterAssemblerTest() override {}
-
-  class InterpreterAssemblerForTest final : public InterpreterAssembler {
-   public:
-    InterpreterAssemblerForTest(InterpreterAssemblerTest* test,
-                                interpreter::Bytecode bytecode)
-        : InterpreterAssembler(test->isolate(), test->zone(), bytecode) {}
-    ~InterpreterAssemblerForTest() override {}
-
-    Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
-                          const Matcher<Node*>& base_matcher,
-                          const Matcher<Node*>& index_matcher);
-    Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher,
-                           const Matcher<Node*>& base_matcher,
-                           const Matcher<Node*>& index_matcher,
-                           const Matcher<Node*>& value_matcher);
-
-    Matcher<Node*> IsBytecodeOperand(int offset);
-    Matcher<Node*> IsBytecodeOperandSignExtended(int offset);
-    Matcher<Node*> IsBytecodeOperandShort(int offset);
-    Matcher<Node*> IsBytecodeOperandShortSignExtended(int offset);
-
-    using InterpreterAssembler::call_descriptor;
-    using InterpreterAssembler::graph;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(InterpreterAssemblerForTest);
-  };
-};
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
-
-#endif  // V8_UNITTESTS_COMPILER_INTERPRETER_ASSEMBLER_UNITTEST_H_
diff --git a/test/unittests/compiler/js-builtin-reducer-unittest.cc b/test/unittests/compiler/js-builtin-reducer-unittest.cc
index 78e9253..9e14cda 100644
--- a/test/unittests/compiler/js-builtin-reducer-unittest.cc
+++ b/test/unittests/compiler/js-builtin-reducer-unittest.cc
@@ -64,10 +64,6 @@
                                   Type::Integral32()};
 
 
-const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
-
-
-// TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering.
 Type* const kNumberTypes[] = {
     Type::UnsignedSmall(), Type::Negative32(),  Type::Unsigned31(),
     Type::SignedSmall(),   Type::Signed32(),    Type::Unsigned32(),
@@ -88,15 +84,13 @@
   Node* control = graph()->start();
   Node* context = UndefinedConstant();
   Node* frame_state = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    Node* call = graph()->NewNode(javascript()->CallFunction(2, language_mode),
-                                  function, UndefinedConstant(), context,
-                                  frame_state, frame_state, effect, control);
-    Reduction r = Reduce(call);
+  Node* call = graph()->NewNode(javascript()->CallFunction(2), function,
+                                UndefinedConstant(), context, frame_state,
+                                frame_state, effect, control);
+  Reduction r = Reduce(call);
 
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
-  }
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
 }
 
 
@@ -107,18 +101,15 @@
   Node* control = graph()->start();
   Node* context = UndefinedConstant();
   Node* frame_state = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    TRACED_FOREACH(Type*, t0, kNumberTypes) {
-      Node* p0 = Parameter(t0, 0);
-      Node* call =
-          graph()->NewNode(javascript()->CallFunction(3, language_mode),
-                           function, UndefinedConstant(), p0, context,
-                           frame_state, frame_state, effect, control);
-      Reduction r = Reduce(call);
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  frame_state, effect, control);
+    Reduction r = Reduce(call);
 
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(r.replacement(), p0);
-    }
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), p0);
   }
 }
 
@@ -130,22 +121,18 @@
   Node* control = graph()->start();
   Node* context = UndefinedConstant();
   Node* frame_state = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    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, language_mode),
-                             function, UndefinedConstant(), p0, p1, context,
-                             frame_state, frame_state, effect, control);
-        Reduction r = Reduce(call);
+  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, frame_state, effect, control);
+      Reduction r = Reduce(call);
 
-        ASSERT_TRUE(r.Changed());
-        EXPECT_THAT(r.replacement(),
-                    IsSelect(MachineRepresentation::kNone,
-                             IsNumberLessThan(p1, p0), p0, p1));
-      }
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kNone,
+                                            IsNumberLessThan(p1, p0), p0, p1));
     }
   }
 }
@@ -162,20 +149,17 @@
   Node* control = graph()->start();
   Node* context = UndefinedConstant();
   Node* frame_state = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    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, language_mode),
-                             function, UndefinedConstant(), p0, p1, context,
-                             frame_state, frame_state, effect, control);
-        Reduction r = Reduce(call);
+  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, frame_state, effect, control);
+      Reduction r = Reduce(call);
 
-        ASSERT_TRUE(r.Changed());
-        EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
-      }
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
     }
   }
 }
@@ -192,18 +176,15 @@
   Node* control = graph()->start();
   Node* context = UndefinedConstant();
   Node* frame_state = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    TRACED_FOREACH(Type*, t0, kNumberTypes) {
-      Node* p0 = Parameter(t0, 0);
-      Node* call =
-          graph()->NewNode(javascript()->CallFunction(3, language_mode),
-                           function, UndefinedConstant(), p0, context,
-                           frame_state, frame_state, effect, control);
-      Reduction r = Reduce(call);
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  frame_state, effect, control);
+    Reduction r = Reduce(call);
 
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
-    }
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
   }
 }
 
diff --git a/test/unittests/compiler/js-context-relaxation-unittest.cc b/test/unittests/compiler/js-context-relaxation-unittest.cc
deleted file mode 100644
index a44bd02..0000000
--- a/test/unittests/compiler/js-context-relaxation-unittest.cc
+++ /dev/null
@@ -1,285 +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/js-context-relaxation.h"
-#include "src/compiler/js-graph.h"
-#include "test/unittests/compiler/graph-unittest.h"
-#include "test/unittests/compiler/node-test-utils.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class JSContextRelaxationTest : public GraphTest {
- public:
-  JSContextRelaxationTest() : GraphTest(3), javascript_(zone()) {}
-  ~JSContextRelaxationTest() override {}
-
- protected:
-  Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
-                                   MachineOperatorBuilder::kNoFlags) {
-    MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
-                                   flags);
-    JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
-                    &machine);
-    // TODO(titzer): mock the GraphReducer here for better unit testing.
-    GraphReducer graph_reducer(zone(), graph());
-    JSContextRelaxation reducer;
-    return reducer.Reduce(node);
-  }
-
-  Node* EmptyFrameState() {
-    MachineOperatorBuilder machine(zone());
-    JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
-                    &machine);
-    return jsgraph.EmptyFrameState();
-  }
-
-  Node* ShallowFrameStateChain(Node* outer_context,
-                               ContextCallingMode context_calling_mode) {
-    const FrameStateFunctionInfo* const frame_state_function_info =
-        common()->CreateFrameStateFunctionInfo(
-            FrameStateType::kJavaScriptFunction, 3, 0,
-            Handle<SharedFunctionInfo>(), context_calling_mode);
-    const Operator* op = common()->FrameState(BailoutId::None(),
-                                              OutputFrameStateCombine::Ignore(),
-                                              frame_state_function_info);
-    return graph()->NewNode(op, graph()->start(), graph()->start(),
-                            graph()->start(), outer_context, graph()->start(),
-                            graph()->start());
-  }
-
-  Node* DeepFrameStateChain(Node* outer_context,
-                            ContextCallingMode context_calling_mode) {
-    const FrameStateFunctionInfo* const frame_state_function_info =
-        common()->CreateFrameStateFunctionInfo(
-            FrameStateType::kJavaScriptFunction, 3, 0,
-            Handle<SharedFunctionInfo>(), context_calling_mode);
-    const Operator* op = common()->FrameState(BailoutId::None(),
-                                              OutputFrameStateCombine::Ignore(),
-                                              frame_state_function_info);
-    Node* shallow_frame_state =
-        ShallowFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-    return graph()->NewNode(op, graph()->start(), graph()->start(),
-                            graph()->start(), graph()->start(),
-                            graph()->start(), shallow_frame_state);
-  }
-
-  JSOperatorBuilder* javascript() { return &javascript_; }
-
- private:
-  JSOperatorBuilder javascript_;
-};
-
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionShallowFrameStateChainNoCrossCtx) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  Node* const frame_state =
-      ShallowFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state, frame_state, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_TRUE(r.Changed());
-  EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionShallowFrameStateChainCrossCtx) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  Node* const frame_state =
-      ShallowFrameStateChain(outer_context, CALL_CHANGES_NATIVE_CONTEXT);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state, frame_state, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_FALSE(r.Changed());
-  EXPECT_EQ(context, NodeProperties::GetContextInput(node));
-}
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionDeepFrameStateChainNoCrossCtx) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  Node* const frame_state =
-      DeepFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state, frame_state, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_TRUE(r.Changed());
-  EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionDeepFrameStateChainCrossCtx) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  Node* const frame_state =
-      DeepFrameStateChain(outer_context, CALL_CHANGES_NATIVE_CONTEXT);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state, frame_state, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_FALSE(r.Changed());
-  EXPECT_EQ(context, NodeProperties::GetContextInput(node));
-}
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionDeepContextChainFullRelaxForCatch) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  const Operator* op = javascript()->CreateCatchContext(Handle<String>());
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* nested_context = graph()->NewNode(
-      op, graph()->start(), graph()->start(), outer_context, effect, control);
-  Node* const frame_state_2 =
-      ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state_2, frame_state_2, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_TRUE(r.Changed());
-  EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionDeepContextChainFullRelaxForWith) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  const Operator* op = javascript()->CreateWithContext();
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* nested_context = graph()->NewNode(
-      op, graph()->start(), graph()->start(), outer_context, effect, control);
-  Node* const frame_state_2 =
-      ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state_2, frame_state_2, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_TRUE(r.Changed());
-  EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionDeepContextChainFullRelaxForBlock) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::null();
-  const Operator* op = javascript()->CreateBlockContext(scope_info);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* nested_context =
-      graph()->NewNode(op, graph()->start(), outer_context, effect, control);
-  Node* const frame_state_2 =
-      ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state_2, frame_state_2, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_TRUE(r.Changed());
-  EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionDeepContextChainPartialRelaxForScript) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::null();
-  const Operator* op = javascript()->CreateScriptContext(scope_info);
-  Node* const frame_state_1 =
-      ShallowFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* nested_context = graph()->NewNode(op, graph()->start(), outer_context,
-                                          frame_state_1, effect, control);
-  Node* const frame_state_2 =
-      ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state_2, frame_state_2, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_TRUE(r.Changed());
-  EXPECT_EQ(nested_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionDeepContextChainPartialRelaxForModule) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  const Operator* op = javascript()->CreateModuleContext();
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* nested_context = graph()->NewNode(
-      op, graph()->start(), graph()->start(), outer_context, effect, control);
-  Node* const frame_state_2 =
-      ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state_2, frame_state_2, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_TRUE(r.Changed());
-  EXPECT_EQ(nested_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
-       RelaxJSCallFunctionDeepContextChainPartialNoRelax) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const outer_context = Parameter(3);
-  const Operator* op = javascript()->CreateFunctionContext(0);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Node* nested_context =
-      graph()->NewNode(op, graph()->start(), outer_context, effect, control);
-  Node* const frame_state_2 =
-      ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
-  Node* node = graph()->NewNode(
-      javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
-      context, frame_state_2, frame_state_2, effect, control);
-  Reduction const r = Reduce(node);
-  EXPECT_FALSE(r.Changed());
-  EXPECT_EQ(context, NodeProperties::GetContextInput(node));
-}
-
-}  // 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
new file mode 100644
index 0000000..837c574
--- /dev/null
+++ b/test/unittests/compiler/js-create-lowering-unittest.cc
@@ -0,0 +1,236 @@
+// Copyright 2016 the V8 project 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/js-create-lowering.h"
+#include "src/code-factory.h"
+#include "src/compiler/access-builder.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/js-operator.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/operator-properties.h"
+#include "src/isolate-inl.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::BitEq;
+using testing::IsNaN;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class JSCreateLoweringTest : public TypedGraphTest {
+ public:
+  JSCreateLoweringTest()
+      : TypedGraphTest(3), javascript_(zone()), deps_(isolate(), zone()) {}
+  ~JSCreateLoweringTest() override {}
+
+ protected:
+  Reduction Reduce(Node* node) {
+    MachineOperatorBuilder machine(zone());
+    SimplifiedOperatorBuilder simplified(zone());
+    JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
+                    &machine);
+    // TODO(titzer): mock the GraphReducer here for better unit testing.
+    GraphReducer graph_reducer(zone(), graph());
+    JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph,
+                             MaybeHandle<LiteralsArray>(), zone());
+    return reducer.Reduce(node);
+  }
+
+  Node* FrameState(Handle<SharedFunctionInfo> shared, Node* outer_frame_state) {
+    Node* state_values = graph()->NewNode(common()->StateValues(0));
+    return graph()->NewNode(
+        common()->FrameState(
+            BailoutId::None(), OutputFrameStateCombine::Ignore(),
+            common()->CreateFrameStateFunctionInfo(
+                FrameStateType::kJavaScriptFunction, 1, 0, shared)),
+        state_values, state_values, state_values, NumberConstant(0),
+        UndefinedConstant(), outer_frame_state);
+  }
+
+  JSOperatorBuilder* javascript() { return &javascript_; }
+
+ private:
+  JSOperatorBuilder javascript_;
+  CompilationDependencies deps_;
+};
+
+TEST_F(JSCreateLoweringTest, JSCreate) {
+  Handle<JSFunction> function = isolate()->object_function();
+  Node* const target = Parameter(Type::Constant(function, graph()->zone()));
+  Node* const context = Parameter(Type::Any());
+  Node* const effect = graph()->start();
+  Reduction r = Reduce(graph()->NewNode(javascript()->Create(), target, target,
+                                        context, EmptyFrameState(), effect));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(
+      r.replacement(),
+      IsFinishRegion(
+          IsAllocate(IsNumberConstant(function->initial_map()->instance_size()),
+                     IsBeginRegion(effect), _),
+          _));
+}
+
+// -----------------------------------------------------------------------------
+// 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));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsFinishRegion(
+                  IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize),
+                             _, control),
+                  _));
+}
+
+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));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsFinishRegion(
+                  IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize),
+                             _, control),
+                  _));
+}
+
+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));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsFinishRegion(
+                  IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _));
+}
+
+// -----------------------------------------------------------------------------
+// JSCreateFunctionContext
+
+TEST_F(JSCreateLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
+  Node* const closure = Parameter(Type::Any());
+  Node* const context = Parameter(Type::Any());
+  Node* const effect = graph()->start();
+  Node* const control = graph()->start();
+  Reduction const r =
+      Reduce(graph()->NewNode(javascript()->CreateFunctionContext(8), closure,
+                              context, effect, control));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
+                                            8 + Context::MIN_CONTEXT_SLOTS)),
+                                        IsBeginRegion(_), control),
+                             _));
+}
+
+// -----------------------------------------------------------------------------
+// JSCreateWithContext
+
+TEST_F(JSCreateLoweringTest, JSCreateWithContext) {
+  Node* const object = Parameter(Type::Receiver());
+  Node* const closure = Parameter(Type::Function());
+  Node* const context = Parameter(Type::Any());
+  Node* const effect = graph()->start();
+  Node* const control = graph()->start();
+  Reduction r =
+      Reduce(graph()->NewNode(javascript()->CreateWithContext(), object,
+                              closure, context, effect, control));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
+                                            Context::MIN_CONTEXT_SLOTS)),
+                                        IsBeginRegion(_), control),
+                             _));
+}
+
+// -----------------------------------------------------------------------------
+// JSCreateCatchContext
+
+TEST_F(JSCreateLoweringTest, JSCreateCatchContext) {
+  Handle<String> name = factory()->length_string();
+  Node* const exception = Parameter(Type::Receiver());
+  Node* const closure = Parameter(Type::Function());
+  Node* const context = Parameter(Type::Any());
+  Node* const effect = graph()->start();
+  Node* const control = graph()->start();
+  Reduction r =
+      Reduce(graph()->NewNode(javascript()->CreateCatchContext(name), exception,
+                              closure, context, effect, control));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
+                                            Context::MIN_CONTEXT_SLOTS + 1)),
+                                        IsBeginRegion(_), control),
+                             _));
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/compiler/js-intrinsic-lowering-unittest.cc b/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
index f38f8ea..919c1b2 100644
--- a/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
+++ b/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
@@ -7,7 +7,6 @@
 #include "src/compiler/js-graph.h"
 #include "src/compiler/js-intrinsic-lowering.h"
 #include "src/compiler/js-operator.h"
-#include "src/types-inl.h"
 #include "test/unittests/compiler/graph-unittest.h"
 #include "test/unittests/compiler/node-test-utils.h"
 #include "testing/gmock-support.h"
@@ -24,9 +23,9 @@
 namespace internal {
 namespace compiler {
 
-class JSIntrinsicLoweringTest : public TypedGraphTest {
+class JSIntrinsicLoweringTest : public GraphTest {
  public:
-  JSIntrinsicLoweringTest() : TypedGraphTest(3), javascript_(zone()) {}
+  JSIntrinsicLoweringTest() : GraphTest(3), javascript_(zone()) {}
   ~JSIntrinsicLoweringTest() override {}
 
  protected:
@@ -162,37 +161,6 @@
 
 
 // -----------------------------------------------------------------------------
-// %_IsDate
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineIsDate) {
-  Node* const input = Parameter(0);
-  Node* const context = Parameter(1);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(
-      graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsDate, 1),
-                       input, context, effect, control));
-  ASSERT_TRUE(r.Changed());
-
-  Node* phi = r.replacement();
-  Capture<Node*> branch, if_false;
-  EXPECT_THAT(
-      phi,
-      IsPhi(
-          MachineRepresentation::kTagged, IsFalseConstant(),
-          IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
-                                    IsLoadField(AccessBuilder::ForMap(), input,
-                                                effect, CaptureEq(&if_false)),
-                                    effect, _),
-                        IsInt32Constant(JS_DATE_TYPE)),
-          IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
-                                 IsBranch(IsObjectIsSmi(input), control))),
-                  AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
-}
-
-
-// -----------------------------------------------------------------------------
 // %_IsTypedArray
 
 
@@ -224,38 +192,6 @@
 
 
 // -----------------------------------------------------------------------------
-// %_IsFunction
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineIsFunction) {
-  Node* const input = Parameter(Type::Any());
-  Node* const context = Parameter(Type::Any());
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(
-      graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsFunction, 1),
-                       input, context, effect, control));
-  ASSERT_TRUE(r.Changed());
-
-  Node* phi = r.replacement();
-  Capture<Node*> branch, if_false;
-  EXPECT_THAT(
-      phi,
-      IsPhi(
-          MachineRepresentation::kTagged, IsFalseConstant(),
-          IsUint32LessThanOrEqual(
-              IsInt32Constant(FIRST_FUNCTION_TYPE),
-              IsLoadField(AccessBuilder::ForMapInstanceType(),
-                          IsLoadField(AccessBuilder::ForMap(), input, effect,
-                                      CaptureEq(&if_false)),
-                          effect, _)),
-          IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
-                                 IsBranch(IsObjectIsSmi(input), control))),
-                  AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
-}
-
-
-// -----------------------------------------------------------------------------
 // %_IsRegExp
 
 
@@ -290,75 +226,16 @@
 // %_IsJSReceiver
 
 
-TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiverWithAny) {
-  Node* const input = Parameter(Type::Any());
-  Node* const context = Parameter(Type::Any());
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(graph()->NewNode(
-      javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
-      context, effect, control));
-  ASSERT_TRUE(r.Changed());
-
-  Node* phi = r.replacement();
-  Capture<Node *> branch, if_false;
-  EXPECT_THAT(
-      phi,
-      IsPhi(
-          MachineRepresentation::kTagged, IsFalseConstant(),
-          IsUint32LessThanOrEqual(
-              IsInt32Constant(FIRST_JS_RECEIVER_TYPE),
-              IsLoadField(AccessBuilder::ForMapInstanceType(),
-                          IsLoadField(AccessBuilder::ForMap(), input, effect,
-                                      CaptureEq(&if_false)),
-                          effect, _)),
-          IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
-                                 IsBranch(IsObjectIsSmi(input), control))),
-                  AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
-}
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiverWithReceiver) {
-  Node* const input = Parameter(Type::Receiver());
-  Node* const context = Parameter(Type::Any());
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(graph()->NewNode(
-      javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
-      context, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsTrueConstant());
-}
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiverWithUndefined) {
-  Node* const input = Parameter(Type::Undefined());
-  Node* const context = Parameter(Type::Any());
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(graph()->NewNode(
-      javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
-      context, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsFalseConstant());
-}
-
-
-// -----------------------------------------------------------------------------
-// %_JSValueGetValue
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineJSValueGetValue) {
+TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiver) {
   Node* const input = Parameter(0);
   Node* const context = Parameter(1);
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
   Reduction const r = Reduce(graph()->NewNode(
-      javascript()->CallRuntime(Runtime::kInlineJSValueGetValue, 1), input,
+      javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
       context, effect, control));
   ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsLoadField(AccessBuilder::ForValue(), input, effect, control));
+  EXPECT_THAT(r.replacement(), IsObjectIsReceiver(input));
 }
 
 
diff --git a/test/unittests/compiler/js-operator-unittest.cc b/test/unittests/compiler/js-operator-unittest.cc
index e0db771..15b1427 100644
--- a/test/unittests/compiler/js-operator-unittest.cc
+++ b/test/unittests/compiler/js-operator-unittest.cc
@@ -12,34 +12,8 @@
 namespace internal {
 namespace compiler {
 
-namespace {
-
-const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
-
-
-#if GTEST_HAS_COMBINE
-
-template <typename T>
-class JSOperatorTestWithLanguageModeAndParam
-    : public TestWithZone,
-      public ::testing::WithParamInterface<::testing::tuple<LanguageMode, T>> {
- protected:
-  LanguageMode language_mode() const {
-    return ::testing::get<0>(B::GetParam());
-  }
-  const T& GetParam() const { return ::testing::get<1>(B::GetParam()); }
-
- private:
-  typedef ::testing::WithParamInterface<::testing::tuple<LanguageMode, T>> B;
-};
-
-#endif  // GTEST_HAS_COMBINE
-
-}  // namespace
-
-
 // -----------------------------------------------------------------------------
-// Shared operators without language mode.
+// Shared operators.
 
 namespace {
 
@@ -56,7 +30,6 @@
   int control_output_count;
 };
 
-
 const SharedOperator kSharedOperators[] = {
 #define SHARED(Name, properties, value_input_count, frame_state_input_count, \
                effect_input_count, control_input_count, value_output_count,  \
@@ -71,6 +44,10 @@
     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),
@@ -148,123 +125,6 @@
 INSTANTIATE_TEST_CASE_P(JSOperatorTest, JSSharedOperatorTest,
                         ::testing::ValuesIn(kSharedOperators));
 
-
-// -----------------------------------------------------------------------------
-// Shared operators with language mode.
-
-
-#if GTEST_HAS_COMBINE
-
-namespace {
-
-struct SharedOperatorWithLanguageMode {
-  const Operator* (JSOperatorBuilder::*constructor)(LanguageMode);
-  IrOpcode::Value opcode;
-  Operator::Properties properties;
-  int value_input_count;
-  int frame_state_input_count;
-  int effect_input_count;
-  int control_input_count;
-  int value_output_count;
-  int effect_output_count;
-  int control_output_count;
-};
-
-
-const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = {
-#define SHARED(Name, properties, value_input_count, frame_state_input_count, \
-               effect_input_count, control_input_count, value_output_count,  \
-               effect_output_count, control_output_count)                    \
-  {                                                                          \
-    &JSOperatorBuilder::Name, IrOpcode::kJS##Name, properties,               \
-        value_input_count, frame_state_input_count, effect_input_count,      \
-        control_input_count, value_output_count, effect_output_count,        \
-        control_output_count                                                 \
-  }
-    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),
-#undef SHARED
-};
-
-
-std::ostream& operator<<(std::ostream& os,
-                         const SharedOperatorWithLanguageMode& sop) {
-  return os << IrOpcode::Mnemonic(sop.opcode);
-}
-
-}  // namespace
-
-
-class JSSharedOperatorWithLanguageModeTest
-    : public JSOperatorTestWithLanguageModeAndParam<
-          SharedOperatorWithLanguageMode> {};
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, InstancesAreGloballyShared) {
-  const SharedOperatorWithLanguageMode& sop = GetParam();
-  JSOperatorBuilder javascript1(zone());
-  JSOperatorBuilder javascript2(zone());
-  EXPECT_EQ((javascript1.*sop.constructor)(language_mode()),
-            (javascript2.*sop.constructor)(language_mode()));
-}
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, NumberOfInputsAndOutputs) {
-  JSOperatorBuilder javascript(zone());
-  const SharedOperatorWithLanguageMode& sop = GetParam();
-  const Operator* op = (javascript.*sop.constructor)(language_mode());
-
-  const int context_input_count = 1;
-  EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
-  EXPECT_EQ(context_input_count, OperatorProperties::GetContextInputCount(op));
-  EXPECT_EQ(sop.frame_state_input_count,
-            OperatorProperties::GetFrameStateInputCount(op));
-  EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
-  EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
-  EXPECT_EQ(sop.value_input_count + context_input_count +
-                sop.frame_state_input_count + sop.effect_input_count +
-                sop.control_input_count,
-            OperatorProperties::GetTotalInputCount(op));
-
-  EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
-  EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
-  EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
-}
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, OpcodeIsCorrect) {
-  JSOperatorBuilder javascript(zone());
-  const SharedOperatorWithLanguageMode& sop = GetParam();
-  const Operator* op = (javascript.*sop.constructor)(language_mode());
-  EXPECT_EQ(sop.opcode, op->opcode());
-}
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, Parameter) {
-  JSOperatorBuilder javascript(zone());
-  const SharedOperatorWithLanguageMode& sop = GetParam();
-  const Operator* op = (javascript.*sop.constructor)(language_mode());
-  EXPECT_EQ(language_mode(), OpParameter<LanguageMode>(op));
-}
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, Properties) {
-  JSOperatorBuilder javascript(zone());
-  const SharedOperatorWithLanguageMode& sop = GetParam();
-  const Operator* op = (javascript.*sop.constructor)(language_mode());
-  EXPECT_EQ(sop.properties, op->properties());
-}
-
-
-INSTANTIATE_TEST_CASE_P(
-    JSOperatorTest, JSSharedOperatorWithLanguageModeTest,
-    ::testing::Combine(::testing::ValuesIn(kLanguageModes),
-                       ::testing::ValuesIn(kSharedOperatorsWithLanguageMode)));
-
-#endif  // GTEST_HAS_COMBINE
-
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc
index 6fc89bb..e37d4a2 100644
--- a/test/unittests/compiler/js-typed-lowering-unittest.cc
+++ b/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -92,18 +92,6 @@
     return reducer.Reduce(node);
   }
 
-  Node* FrameState(Handle<SharedFunctionInfo> shared, Node* outer_frame_state) {
-    Node* state_values = graph()->NewNode(common()->StateValues(0));
-    return graph()->NewNode(
-        common()->FrameState(BailoutId::None(),
-                             OutputFrameStateCombine::Ignore(),
-                             common()->CreateFrameStateFunctionInfo(
-                                 FrameStateType::kJavaScriptFunction, 1, 0,
-                                 shared, CALL_MAINTAINS_NATIVE_CONTEXT)),
-        state_values, state_values, state_values, NumberConstant(0),
-        UndefinedConstant(), outer_frame_state);
-  }
-
   Handle<JSArrayBuffer> NewArrayBuffer(void* bytes, size_t byte_length) {
     Handle<JSArrayBuffer> buffer = factory()->NewJSArrayBuffer();
     JSArrayBuffer::Setup(buffer, isolate(), true, bytes, byte_length);
@@ -435,15 +423,12 @@
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
   TRACED_FORRANGE(double, rhs, 0, 31) {
-    TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-      Reduction r = Reduce(
-          graph()->NewNode(javascript()->ShiftLeft(language_mode, hints), lhs,
-                           NumberConstant(rhs), context, EmptyFrameState(),
-                           EmptyFrameState(), effect, control));
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(r.replacement(),
-                  IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs))));
-    }
+    Reduction r = Reduce(graph()->NewNode(
+        javascript()->ShiftLeft(hints), lhs, NumberConstant(rhs), context,
+        EmptyFrameState(), EmptyFrameState(), effect, control));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs))));
   }
 }
 
@@ -455,13 +440,11 @@
   Node* const context = UndefinedConstant();
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    Reduction r = Reduce(graph()->NewNode(
-        javascript()->ShiftLeft(language_mode, hints), lhs, rhs, context,
-        EmptyFrameState(), EmptyFrameState(), effect, control));
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs));
-  }
+  Reduction r = Reduce(graph()->NewNode(javascript()->ShiftLeft(hints), lhs,
+                                        rhs, context, EmptyFrameState(),
+                                        EmptyFrameState(), effect, control));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs));
 }
 
 
@@ -476,15 +459,12 @@
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
   TRACED_FORRANGE(double, rhs, 0, 31) {
-    TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-      Reduction r = Reduce(
-          graph()->NewNode(javascript()->ShiftRight(language_mode, hints), lhs,
-                           NumberConstant(rhs), context, EmptyFrameState(),
-                           EmptyFrameState(), effect, control));
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(r.replacement(),
-                  IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs))));
-    }
+    Reduction r = Reduce(graph()->NewNode(
+        javascript()->ShiftRight(hints), lhs, NumberConstant(rhs), context,
+        EmptyFrameState(), EmptyFrameState(), effect, control));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs))));
   }
 }
 
@@ -496,13 +476,11 @@
   Node* const context = UndefinedConstant();
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    Reduction r = Reduce(graph()->NewNode(
-        javascript()->ShiftRight(language_mode, hints), lhs, rhs, context,
-        EmptyFrameState(), EmptyFrameState(), effect, control));
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs));
-  }
+  Reduction r = Reduce(graph()->NewNode(javascript()->ShiftRight(hints), lhs,
+                                        rhs, context, EmptyFrameState(),
+                                        EmptyFrameState(), effect, control));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs));
 }
 
 
@@ -518,15 +496,12 @@
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
   TRACED_FORRANGE(double, rhs, 0, 31) {
-    TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-      Reduction r = Reduce(graph()->NewNode(
-          javascript()->ShiftRightLogical(language_mode, hints), lhs,
-          NumberConstant(rhs), context, EmptyFrameState(), EmptyFrameState(),
-          effect, control));
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(r.replacement(),
-                  IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs))));
-    }
+    Reduction r = Reduce(graph()->NewNode(
+        javascript()->ShiftRightLogical(hints), lhs, NumberConstant(rhs),
+        context, EmptyFrameState(), EmptyFrameState(), effect, control));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs))));
   }
 }
 
@@ -538,13 +513,11 @@
   Node* const context = UndefinedConstant();
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    Reduction r = Reduce(graph()->NewNode(
-        javascript()->ShiftRightLogical(language_mode, hints), lhs, rhs,
-        context, EmptyFrameState(), EmptyFrameState(), effect, control));
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs));
-  }
+  Reduction r = Reduce(graph()->NewNode(javascript()->ShiftRightLogical(hints),
+                                        lhs, rhs, context, EmptyFrameState(),
+                                        EmptyFrameState(), effect, control));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs));
 }
 
 
@@ -627,37 +600,34 @@
       NewArrayBuffer(backing_store, sizeof(backing_store));
   VectorSlotPair feedback;
   TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
-    TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-      Handle<JSTypedArray> array =
-          factory()->NewJSTypedArray(type, buffer, 0, kLength);
-      int const element_size = static_cast<int>(array->element_size());
+    Handle<JSTypedArray> array =
+        factory()->NewJSTypedArray(type, buffer, 0, kLength);
+    int const element_size = static_cast<int>(array->element_size());
 
-      Node* key = Parameter(
-          Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
-      Node* base = HeapConstant(array);
-      Node* vector = UndefinedConstant();
-      Node* context = UndefinedConstant();
-      Node* effect = graph()->start();
-      Node* control = graph()->start();
-      Reduction r = Reduce(
-          graph()->NewNode(javascript()->LoadProperty(language_mode, feedback),
-                           base, key, vector, context, EmptyFrameState(),
-                           EmptyFrameState(), effect, control));
+    Node* key = Parameter(
+        Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
+    Node* base = HeapConstant(array);
+    Node* vector = UndefinedConstant();
+    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));
 
-      Matcher<Node*> offset_matcher =
-          element_size == 1
-              ? key
-              : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
+    Matcher<Node*> offset_matcher =
+        element_size == 1
+            ? key
+            : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
 
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(
-          r.replacement(),
-          IsLoadBuffer(BufferAccess(type),
-                       IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
-                       offset_matcher,
-                       IsNumberConstant(array->byte_length()->Number()), effect,
-                       control));
-    }
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(
+        r.replacement(),
+        IsLoadBuffer(BufferAccess(type),
+                     IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
+                     offset_matcher,
+                     IsNumberConstant(array->byte_length()->Number()), effect,
+                     control));
   }
 }
 
@@ -669,32 +639,29 @@
       NewArrayBuffer(backing_store, sizeof(backing_store));
   VectorSlotPair feedback;
   TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
-    TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-      Handle<JSTypedArray> array =
-          factory()->NewJSTypedArray(type, buffer, 0, kLength);
-      ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
+    Handle<JSTypedArray> array =
+        factory()->NewJSTypedArray(type, buffer, 0, kLength);
+    ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
 
-      int min = random_number_generator()->NextInt(static_cast<int>(kLength));
-      int max = random_number_generator()->NextInt(static_cast<int>(kLength));
-      if (min > max) std::swap(min, max);
-      Node* key = Parameter(Type::Range(min, max, zone()));
-      Node* base = HeapConstant(array);
-      Node* vector = UndefinedConstant();
-      Node* context = UndefinedConstant();
-      Node* effect = graph()->start();
-      Node* control = graph()->start();
-      Reduction r = Reduce(
-          graph()->NewNode(javascript()->LoadProperty(language_mode, feedback),
-                           base, key, vector, context, EmptyFrameState(),
-                           EmptyFrameState(), effect, control));
+    int min = random_number_generator()->NextInt(static_cast<int>(kLength));
+    int max = random_number_generator()->NextInt(static_cast<int>(kLength));
+    if (min > max) std::swap(min, max);
+    Node* key = Parameter(Type::Range(min, max, zone()));
+    Node* base = HeapConstant(array);
+    Node* vector = UndefinedConstant();
+    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));
 
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(
-          r.replacement(),
-          IsLoadElement(access,
-                        IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
-                        key, effect, control));
-    }
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(
+        r.replacement(),
+        IsLoadElement(access,
+                      IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
+                      key, effect, control));
   }
 }
 
@@ -847,15 +814,12 @@
   Node* const context = UndefinedConstant();
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    Reduction const r = Reduce(
-        graph()->NewNode(javascript()->LoadNamed(language_mode, name, feedback),
-                         receiver, vector, context, EmptyFrameState(),
-                         EmptyFrameState(), effect, control));
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
-                                             receiver, effect, control));
-  }
+  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(), IsLoadField(AccessBuilder::ForStringLength(),
+                                           receiver, effect, control));
 }
 
 
@@ -869,14 +833,11 @@
   Node* const context = Parameter(Type::Internal(), 2);
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
-    Reduction const r = Reduce(
-        graph()->NewNode(javascript()->LoadNamed(language_mode, name, feedback),
-                         receiver, vector, context, EmptyFrameState(),
-                         EmptyFrameState(), effect, control));
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsHeapConstant(function_prototype));
-  }
+  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));
 }
 
 
@@ -886,7 +847,6 @@
 
 TEST_F(JSTypedLoweringTest, JSAddWithString) {
   BinaryOperationHints const hints = BinaryOperationHints::Any();
-  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
     Node* lhs = Parameter(Type::String(), 0);
     Node* rhs = Parameter(Type::String(), 1);
     Node* context = Parameter(Type::Any(), 2);
@@ -894,300 +854,15 @@
     Node* frame_state1 = EmptyFrameState();
     Node* effect = graph()->start();
     Node* control = graph()->start();
-    Reduction r = Reduce(
-        graph()->NewNode(javascript()->Add(language_mode, hints), lhs, rhs,
-                         context, frame_state0, frame_state1, effect, control));
+    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(),
                 IsCall(_, IsHeapConstant(CodeFactory::StringAdd(
                                              isolate(), STRING_ADD_CHECK_NONE,
                                              NOT_TENURED).code()),
                        lhs, rhs, context, frame_state0, effect, control));
-  }
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreate
-
-
-TEST_F(JSTypedLoweringTest, JSCreate) {
-  Handle<JSFunction> function = isolate()->object_function();
-  Node* const target = Parameter(Type::Constant(function, graph()->zone()));
-  Node* const context = Parameter(Type::Any());
-  Node* const effect = graph()->start();
-  Reduction r = Reduce(graph()->NewNode(javascript()->Create(), target, target,
-                                        context, EmptyFrameState(), effect));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(
-      r.replacement(),
-      IsFinishRegion(
-          IsAllocate(IsNumberConstant(function->initial_map()->instance_size()),
-                     IsBeginRegion(effect), _),
-          _));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateArguments
-
-
-TEST_F(JSTypedLoweringTest, 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(
-                           CreateArgumentsParameters::kMappedArguments, 0),
-                       closure, context, frame_state, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsCall(_, IsHeapConstant(CodeFactory::ArgumentsAccess(
-                                           isolate(), false, false)
-                                           .code()),
-                     closure, IsNumberConstant(0), _, effect, control));
-}
-
-
-TEST_F(JSTypedLoweringTest, JSCreateArgumentsRestArrayViaStub) {
-  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(CreateArgumentsParameters::kRestArray, 0),
-      closure, context, frame_state, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(
-      r.replacement(),
-      IsCall(_,
-             IsHeapConstant(CodeFactory::RestArgumentsAccess(isolate()).code()),
-             IsNumberConstant(0), _, IsNumberConstant(0), _, effect, control));
-}
-
-
-TEST_F(JSTypedLoweringTest, 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(
-                           CreateArgumentsParameters::kMappedArguments, 0),
-                       closure, context, frame_state_inner, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsFinishRegion(
-                  IsAllocate(IsNumberConstant(Heap::kSloppyArgumentsObjectSize),
-                             _, control),
-                  _));
-}
-
-
-TEST_F(JSTypedLoweringTest, 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(
-                           CreateArgumentsParameters::kUnmappedArguments, 0),
-                       closure, context, frame_state_inner, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsFinishRegion(
-                  IsAllocate(IsNumberConstant(Heap::kStrictArgumentsObjectSize),
-                             _, control),
-                  _));
-}
-
-
-TEST_F(JSTypedLoweringTest, 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(CreateArgumentsParameters::kRestArray, 0),
-      closure, context, frame_state_inner, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsFinishRegion(
-                  IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateClosure
-
-
-TEST_F(JSTypedLoweringTest, JSCreateClosure) {
-  Node* const context = UndefinedConstant();
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->CreateClosure(shared, NOT_TENURED),
-                              context, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsCall(_, IsHeapConstant(CodeFactory::FastNewClosure(
-                                           isolate(), shared->language_mode(),
-                                           shared->kind()).code()),
-                     IsHeapConstant(shared), effect, control));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateLiteralArray
-
-
-TEST_F(JSTypedLoweringTest, JSCreateLiteralArray) {
-  Handle<FixedArray> const constant_elements = factory()->NewFixedArray(12);
-  int const literal_flags = ArrayLiteral::kShallowElements;
-  int const literal_index = 1;
-  Node* const closure = Parameter(0);
-  Node* const context = Parameter(1);
-  Node* const frame_state = EmptyFrameState();
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(
-      graph()->NewNode(javascript()->CreateLiteralArray(
-                           constant_elements, literal_flags, literal_index),
-                       closure, context, frame_state, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(
-      r.replacement(),
-      IsCall(_, IsHeapConstant(
-                    CodeFactory::FastCloneShallowArray(isolate()).code()),
-             closure, IsNumberConstant(literal_index),
-             IsHeapConstant(constant_elements), context, frame_state, effect,
-             control));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateLiteralObject
-
-
-TEST_F(JSTypedLoweringTest, JSCreateLiteralObject) {
-  Handle<FixedArray> const constant_properties =
-      factory()->NewFixedArray(6 * 2);
-  int const literal_flags = ObjectLiteral::kShallowProperties;
-  int const literal_index = 1;
-  Node* const closure = Parameter(0);
-  Node* const context = Parameter(1);
-  Node* const frame_state = EmptyFrameState();
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(
-      graph()->NewNode(javascript()->CreateLiteralObject(
-                           constant_properties, literal_flags, literal_index),
-                       closure, context, frame_state, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(
-      r.replacement(),
-      IsCall(_, IsHeapConstant(
-                    CodeFactory::FastCloneShallowObject(isolate(), 6).code()),
-             closure, IsNumberConstant(literal_index),
-             IsHeapConstant(constant_properties), _, context, frame_state,
-             effect, control));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateFunctionContext
-
-
-TEST_F(JSTypedLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
-  Node* const closure = Parameter(Type::Any());
-  Node* const context = Parameter(Type::Any());
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r =
-      Reduce(graph()->NewNode(javascript()->CreateFunctionContext(8), closure,
-                              context, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
-                                            8 + Context::MIN_CONTEXT_SLOTS)),
-                                        IsBeginRegion(_), control),
-                             _));
-}
-
-
-TEST_F(JSTypedLoweringTest, JSCreateFunctionContextViaStub) {
-  Node* const closure = Parameter(Type::Any());
-  Node* const context = Parameter(Type::Any());
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r =
-      Reduce(graph()->NewNode(javascript()->CreateFunctionContext(32), closure,
-                              context, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsCall(_, IsHeapConstant(
-                            CodeFactory::FastNewContext(isolate(), 32).code()),
-                     closure, context, effect, control));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateWithContext
-
-
-TEST_F(JSTypedLoweringTest, JSCreateWithContext) {
-  Node* const object = Parameter(Type::Receiver());
-  Node* const closure = Parameter(Type::Function());
-  Node* const context = Parameter(Type::Any());
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->CreateWithContext(), object,
-                              closure, context, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
-                                            Context::MIN_CONTEXT_SLOTS)),
-                                        IsBeginRegion(_), control),
-                             _));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateCatchContext
-
-
-TEST_F(JSTypedLoweringTest, JSCreateCatchContext) {
-  Handle<String> name = factory()->length_string();
-  Node* const exception = Parameter(Type::Receiver());
-  Node* const closure = Parameter(Type::Function());
-  Node* const context = Parameter(Type::Any());
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->CreateCatchContext(name), exception,
-                              closure, context, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
-                                            Context::MIN_CONTEXT_SLOTS + 1)),
-                                        IsBeginRegion(_), control),
-                             _));
 }
 
 
diff --git a/test/unittests/compiler/liveness-analyzer-unittest.cc b/test/unittests/compiler/liveness-analyzer-unittest.cc
index b77830a..efc823d 100644
--- a/test/unittests/compiler/liveness-analyzer-unittest.cc
+++ b/test/unittests/compiler/liveness-analyzer-unittest.cc
@@ -61,7 +61,7 @@
     const FrameStateFunctionInfo* state_info =
         common()->CreateFrameStateFunctionInfo(
             FrameStateType::kJavaScriptFunction, 0, locals_count_,
-            Handle<SharedFunctionInfo>(), CALL_MAINTAINS_NATIVE_CONTEXT);
+            Handle<SharedFunctionInfo>());
 
     const Operator* op = common()->FrameState(
         BailoutId(ast_num), OutputFrameStateCombine::Ignore(), state_info);
diff --git a/test/unittests/compiler/move-optimizer-unittest.cc b/test/unittests/compiler/move-optimizer-unittest.cc
index 413c58b..5ccd0c6 100644
--- a/test/unittests/compiler/move-optimizer-unittest.cc
+++ b/test/unittests/compiler/move-optimizer-unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "src/compiler/move-optimizer.h"
+#include "src/compiler/pipeline.h"
 #include "test/unittests/compiler/instruction-sequence-unittest.h"
 
 namespace v8 {
@@ -227,8 +228,8 @@
       ctant_def->GetParallelMove(Instruction::GapPosition::END);
   ParallelMove* last_start =
       last->GetParallelMove(Instruction::GapPosition::START);
-  CHECK(inst1_start == nullptr || inst1_start->size() == 0);
-  CHECK(inst1_end == nullptr || inst1_end->size() == 0);
+  CHECK(inst1_start == nullptr || NonRedundantSize(inst1_start) == 0);
+  CHECK(inst1_end == nullptr || NonRedundantSize(inst1_end) == 0);
   CHECK(last_start->size() == 2);
   int redundants = 0;
   int assignment = 0;
@@ -246,6 +247,98 @@
 }
 
 
+TEST_F(MoveOptimizerTest, SubsetMovesMerge) {
+  StartBlock();
+  EndBlock(Branch(Imm(), 1, 2));
+
+  StartBlock();
+  EndBlock(Jump(2));
+  Instruction* last_move_b1 = LastInstruction();
+  AddMove(last_move_b1, Reg(0), Reg(1));
+  AddMove(last_move_b1, Reg(2), Reg(3));
+
+  StartBlock();
+  EndBlock(Jump(1));
+  Instruction* last_move_b2 = LastInstruction();
+  AddMove(last_move_b2, Reg(0), Reg(1));
+  AddMove(last_move_b2, Reg(4), Reg(5));
+
+  StartBlock();
+  EndBlock(Last());
+
+  Instruction* last = LastInstruction();
+
+  Optimize();
+
+  ParallelMove* last_move = last->parallel_moves()[0];
+  CHECK_EQ(1, NonRedundantSize(last_move));
+  CHECK(Contains(last_move, Reg(0), Reg(1)));
+
+  ParallelMove* b1_move = last_move_b1->parallel_moves()[0];
+  CHECK_EQ(1, NonRedundantSize(b1_move));
+  CHECK(Contains(b1_move, Reg(2), Reg(3)));
+
+  ParallelMove* b2_move = last_move_b2->parallel_moves()[0];
+  CHECK_EQ(1, NonRedundantSize(b2_move));
+  CHECK(Contains(b2_move, Reg(4), Reg(5)));
+}
+
+
+TEST_F(MoveOptimizerTest, GapConflictSubsetMovesDoNotMerge) {
+  StartBlock();
+  EndBlock(Branch(Imm(), 1, 2));
+
+  StartBlock();
+  EndBlock(Jump(2));
+  Instruction* last_move_b1 = LastInstruction();
+  AddMove(last_move_b1, Reg(0), Reg(1));
+  AddMove(last_move_b1, Reg(2), Reg(0));
+  AddMove(last_move_b1, Reg(4), Reg(5));
+
+  StartBlock();
+  EndBlock(Jump(1));
+  Instruction* last_move_b2 = LastInstruction();
+  AddMove(last_move_b2, Reg(0), Reg(1));
+  AddMove(last_move_b2, Reg(4), Reg(5));
+
+  StartBlock();
+  EndBlock(Last());
+
+  Instruction* last = LastInstruction();
+
+  Optimize();
+
+  ParallelMove* last_move = last->parallel_moves()[0];
+  CHECK_EQ(1, NonRedundantSize(last_move));
+  CHECK(Contains(last_move, Reg(4), Reg(5)));
+
+  ParallelMove* b1_move = last_move_b1->parallel_moves()[0];
+  CHECK_EQ(2, NonRedundantSize(b1_move));
+  CHECK(Contains(b1_move, Reg(0), Reg(1)));
+  CHECK(Contains(b1_move, Reg(2), Reg(0)));
+
+  ParallelMove* b2_move = last_move_b2->parallel_moves()[0];
+  CHECK_EQ(1, NonRedundantSize(b2_move));
+  CHECK(Contains(b1_move, Reg(0), Reg(1)));
+}
+
+TEST_F(MoveOptimizerTest, ClobberedDestinationsAreEliminated) {
+  StartBlock();
+  EmitNop();
+  Instruction* first_instr = LastInstruction();
+  AddMove(first_instr, Reg(0), Reg(1));
+  EmitOI(Reg(1), 0, nullptr);
+  Instruction* last_instr = LastInstruction();
+  EndBlock();
+  Optimize();
+
+  ParallelMove* first_move = first_instr->parallel_moves()[0];
+  CHECK_EQ(0, NonRedundantSize(first_move));
+
+  ParallelMove* last_move = last_instr->parallel_moves()[0];
+  CHECK_EQ(0, NonRedundantSize(last_move));
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/compiler/node-test-utils.cc b/test/unittests/compiler/node-test-utils.cc
index 54168ee..ee4cf54 100644
--- a/test/unittests/compiler/node-test-utils.cc
+++ b/test/unittests/compiler/node-test-utils.cc
@@ -323,13 +323,30 @@
                   const Matcher<Node*>& control_matcher)
       : NodeMatcher(IrOpcode::kReturn),
         value_matcher_(value_matcher),
+        value2_matcher_(_),
         effect_matcher_(effect_matcher),
-        control_matcher_(control_matcher) {}
+        control_matcher_(control_matcher),
+        has_second_return_value_(false) {}
+
+  IsReturnMatcher(const Matcher<Node*>& value_matcher,
+                  const Matcher<Node*>& value2_matcher,
+                  const Matcher<Node*>& effect_matcher,
+                  const Matcher<Node*>& control_matcher)
+      : NodeMatcher(IrOpcode::kReturn),
+        value_matcher_(value_matcher),
+        value2_matcher_(value2_matcher),
+        effect_matcher_(effect_matcher),
+        control_matcher_(control_matcher),
+        has_second_return_value_(true) {}
 
   void DescribeTo(std::ostream* os) const final {
     NodeMatcher::DescribeTo(os);
     *os << " whose value (";
     value_matcher_.DescribeTo(os);
+    if (has_second_return_value_) {
+      *os << ") and second value (";
+      value2_matcher_.DescribeTo(os);
+    }
     *os << ") and effect (";
     effect_matcher_.DescribeTo(os);
     *os << ") and control (";
@@ -341,6 +358,9 @@
     return (NodeMatcher::MatchAndExplain(node, listener) &&
             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
                                  "value", value_matcher_, listener) &&
+            (!has_second_return_value_ ||
+             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
+                                  "value2", value2_matcher_, listener)) &&
             PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
                                  effect_matcher_, listener) &&
             PrintMatchAndExplain(NodeProperties::GetControlInput(node),
@@ -349,8 +369,10 @@
 
  private:
   const Matcher<Node*> value_matcher_;
+  const Matcher<Node*> value2_matcher_;
   const Matcher<Node*> effect_matcher_;
   const Matcher<Node*> control_matcher_;
+  bool has_second_return_value_;
 };
 
 
@@ -1467,7 +1489,6 @@
   return MakeMatcher(new NodeMatcher(IrOpcode::kDead));
 }
 
-
 Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher) {
   return MakeMatcher(new IsControl1Matcher(IrOpcode::kEnd, control0_matcher));
 }
@@ -1577,6 +1598,13 @@
       new IsReturnMatcher(value_matcher, effect_matcher, control_matcher));
 }
 
+Matcher<Node*> IsReturn2(const Matcher<Node*>& value_matcher,
+                         const Matcher<Node*>& value2_matcher,
+                         const Matcher<Node*>& effect_matcher,
+                         const Matcher<Node*>& control_matcher) {
+  return MakeMatcher(new IsReturnMatcher(value_matcher, value2_matcher,
+                                         effect_matcher, control_matcher));
+}
 
 Matcher<Node*> IsTerminate(const Matcher<Node*>& effect_matcher,
                            const Matcher<Node*>& control_matcher) {
@@ -1675,6 +1703,15 @@
   return MakeMatcher(new IsProjectionMatcher(index_matcher, base_matcher));
 }
 
+Matcher<Node*> IsCall(const Matcher<const CallDescriptor*>& descriptor_matcher,
+                      const Matcher<Node*>& value0_matcher,
+                      const Matcher<Node*>& effect_matcher,
+                      const Matcher<Node*>& control_matcher) {
+  std::vector<Matcher<Node*>> value_matchers;
+  value_matchers.push_back(value0_matcher);
+  return MakeMatcher(new IsCallMatcher(descriptor_matcher, value_matchers,
+                                       effect_matcher, control_matcher));
+}
 
 Matcher<Node*> IsCall(const Matcher<const CallDescriptor*>& descriptor_matcher,
                       const Matcher<Node*>& value0_matcher,
@@ -2106,6 +2143,7 @@
 IS_UNOP_MATCHER(Float64ExtractHighWord32)
 IS_UNOP_MATCHER(NumberToInt32)
 IS_UNOP_MATCHER(NumberToUint32)
+IS_UNOP_MATCHER(ObjectIsReceiver)
 IS_UNOP_MATCHER(ObjectIsSmi)
 IS_UNOP_MATCHER(Word32Clz)
 #undef IS_UNOP_MATCHER
diff --git a/test/unittests/compiler/node-test-utils.h b/test/unittests/compiler/node-test-utils.h
index 8592f30..03f2a3b 100644
--- a/test/unittests/compiler/node-test-utils.h
+++ b/test/unittests/compiler/node-test-utils.h
@@ -17,11 +17,8 @@
 template <typename T>
 class Handle;
 class HeapObject;
-template <class>
-class TypeImpl;
+class Type;
 enum TypeofMode : int;
-struct ZoneTypeConfig;
-typedef TypeImpl<ZoneTypeConfig> Type;
 
 namespace compiler {
 
@@ -70,6 +67,10 @@
 Matcher<Node*> IsReturn(const Matcher<Node*>& value_matcher,
                         const Matcher<Node*>& effect_matcher,
                         const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsReturn2(const Matcher<Node*>& value_matcher,
+                         const Matcher<Node*>& value2_matcher,
+                         const Matcher<Node*>& effect_matcher,
+                         const Matcher<Node*>& control_matcher);
 Matcher<Node*> IsTerminate(const Matcher<Node*>& effect_matcher,
                            const Matcher<Node*>& control_matcher);
 Matcher<Node*> IsExternalConstant(
@@ -246,6 +247,7 @@
                               const Matcher<Node*>& value_matcher,
                               const Matcher<Node*>& effect_matcher,
                               const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsObjectIsReceiver(const Matcher<Node*>& value_matcher);
 Matcher<Node*> IsObjectIsSmi(const Matcher<Node*>& value_matcher);
 
 Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
diff --git a/test/unittests/compiler/scheduler-rpo-unittest.cc b/test/unittests/compiler/scheduler-rpo-unittest.cc
new file mode 100644
index 0000000..713ee6e
--- /dev/null
+++ b/test/unittests/compiler/scheduler-rpo-unittest.cc
@@ -0,0 +1,533 @@
+// 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/schedule.h"
+#include "src/compiler/scheduler.h"
+#include "test/unittests/compiler/compiler-test-utils.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::AnyOf;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class SchedulerRPOTest : public TestWithZone {
+ public:
+  SchedulerRPOTest() {}
+
+  void CheckRPONumbers(BasicBlockVector* order, size_t expected,
+                       bool loops_allowed) {
+    CHECK(expected == order->size());
+    for (int i = 0; i < static_cast<int>(order->size()); i++) {
+      CHECK(order->at(i)->rpo_number() == i);
+      if (!loops_allowed) {
+        CHECK(!order->at(i)->loop_end());
+        CHECK(!order->at(i)->loop_header());
+      }
+    }
+  }
+
+  void CheckLoop(BasicBlockVector* order, BasicBlock** blocks, int body_size) {
+    BasicBlock* header = blocks[0];
+    BasicBlock* end = header->loop_end();
+    CHECK(end);
+    CHECK_GT(end->rpo_number(), 0);
+    CHECK_EQ(body_size, end->rpo_number() - header->rpo_number());
+    for (int i = 0; i < body_size; i++) {
+      CHECK_GE(blocks[i]->rpo_number(), header->rpo_number());
+      CHECK_LT(blocks[i]->rpo_number(), end->rpo_number());
+      CHECK(header->LoopContains(blocks[i]));
+      CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header);
+    }
+    if (header->rpo_number() > 0) {
+      CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header);
+    }
+    if (end->rpo_number() < static_cast<int>(order->size())) {
+      CHECK_NE(order->at(end->rpo_number())->loop_header(), header);
+    }
+  }
+
+  struct TestLoop {
+    int count;
+    BasicBlock** nodes;
+    BasicBlock* header() { return nodes[0]; }
+    BasicBlock* last() { return nodes[count - 1]; }
+    ~TestLoop() { delete[] nodes; }
+  };
+
+  TestLoop* CreateLoop(Schedule* schedule, int count) {
+    TestLoop* loop = new TestLoop();
+    loop->count = count;
+    loop->nodes = new BasicBlock*[count];
+    for (int i = 0; i < count; i++) {
+      loop->nodes[i] = schedule->NewBasicBlock();
+      if (i > 0) {
+        schedule->AddSuccessorForTesting(loop->nodes[i - 1], loop->nodes[i]);
+      }
+    }
+    schedule->AddSuccessorForTesting(loop->nodes[count - 1], loop->nodes[0]);
+    return loop;
+  }
+};
+
+TEST_F(SchedulerRPOTest, Degenerate1) {
+  Schedule schedule(zone());
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 1, false);
+  EXPECT_EQ(schedule.start(), order->at(0));
+}
+
+TEST_F(SchedulerRPOTest, Degenerate2) {
+  Schedule schedule(zone());
+
+  schedule.AddGoto(schedule.start(), schedule.end());
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 2, false);
+  EXPECT_EQ(schedule.start(), order->at(0));
+  EXPECT_EQ(schedule.end(), order->at(1));
+}
+
+TEST_F(SchedulerRPOTest, Line) {
+  for (int i = 0; i < 10; i++) {
+    Schedule schedule(zone());
+
+    BasicBlock* last = schedule.start();
+    for (int j = 0; j < i; j++) {
+      BasicBlock* block = schedule.NewBasicBlock();
+      block->set_deferred(i & 1);
+      schedule.AddGoto(last, block);
+      last = block;
+    }
+    BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+    CheckRPONumbers(order, 1 + i, false);
+
+    for (size_t i = 0; i < schedule.BasicBlockCount(); i++) {
+      BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i));
+      if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) {
+        EXPECT_EQ(block->rpo_number() + 1, block->SuccessorAt(0)->rpo_number());
+      }
+    }
+  }
+}
+
+TEST_F(SchedulerRPOTest, SelfLoop) {
+  Schedule schedule(zone());
+  schedule.AddSuccessorForTesting(schedule.start(), schedule.start());
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 1, true);
+  BasicBlock* loop[] = {schedule.start()};
+  CheckLoop(order, loop, 1);
+}
+
+TEST_F(SchedulerRPOTest, EntryLoop) {
+  Schedule schedule(zone());
+  BasicBlock* body = schedule.NewBasicBlock();
+  schedule.AddSuccessorForTesting(schedule.start(), body);
+  schedule.AddSuccessorForTesting(body, schedule.start());
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 2, true);
+  BasicBlock* loop[] = {schedule.start(), body};
+  CheckLoop(order, loop, 2);
+}
+
+TEST_F(SchedulerRPOTest, EndLoop) {
+  Schedule schedule(zone());
+  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
+  schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 3, true);
+  CheckLoop(order, loop1->nodes, loop1->count);
+}
+
+TEST_F(SchedulerRPOTest, EndLoopNested) {
+  Schedule schedule(zone());
+  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
+  schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
+  schedule.AddSuccessorForTesting(loop1->last(), schedule.start());
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 3, true);
+  CheckLoop(order, loop1->nodes, loop1->count);
+}
+
+TEST_F(SchedulerRPOTest, Diamond) {
+  Schedule schedule(zone());
+
+  BasicBlock* A = schedule.start();
+  BasicBlock* B = schedule.NewBasicBlock();
+  BasicBlock* C = schedule.NewBasicBlock();
+  BasicBlock* D = schedule.end();
+
+  schedule.AddSuccessorForTesting(A, B);
+  schedule.AddSuccessorForTesting(A, C);
+  schedule.AddSuccessorForTesting(B, D);
+  schedule.AddSuccessorForTesting(C, D);
+
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 4, false);
+
+  EXPECT_EQ(0, A->rpo_number());
+  EXPECT_THAT(B->rpo_number(), AnyOf(1, 2));
+  EXPECT_THAT(C->rpo_number(), AnyOf(1, 2));
+  EXPECT_EQ(3, D->rpo_number());
+}
+
+TEST_F(SchedulerRPOTest, Loop1) {
+  Schedule schedule(zone());
+
+  BasicBlock* A = schedule.start();
+  BasicBlock* B = schedule.NewBasicBlock();
+  BasicBlock* C = schedule.NewBasicBlock();
+  BasicBlock* D = schedule.end();
+
+  schedule.AddSuccessorForTesting(A, B);
+  schedule.AddSuccessorForTesting(B, C);
+  schedule.AddSuccessorForTesting(C, B);
+  schedule.AddSuccessorForTesting(C, D);
+
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 4, true);
+  BasicBlock* loop[] = {B, C};
+  CheckLoop(order, loop, 2);
+}
+
+TEST_F(SchedulerRPOTest, Loop2) {
+  Schedule schedule(zone());
+
+  BasicBlock* A = schedule.start();
+  BasicBlock* B = schedule.NewBasicBlock();
+  BasicBlock* C = schedule.NewBasicBlock();
+  BasicBlock* D = schedule.end();
+
+  schedule.AddSuccessorForTesting(A, B);
+  schedule.AddSuccessorForTesting(B, C);
+  schedule.AddSuccessorForTesting(C, B);
+  schedule.AddSuccessorForTesting(B, D);
+
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 4, true);
+  BasicBlock* loop[] = {B, C};
+  CheckLoop(order, loop, 2);
+}
+
+TEST_F(SchedulerRPOTest, LoopN) {
+  for (int i = 0; i < 11; i++) {
+    Schedule schedule(zone());
+    BasicBlock* A = schedule.start();
+    BasicBlock* B = schedule.NewBasicBlock();
+    BasicBlock* C = schedule.NewBasicBlock();
+    BasicBlock* D = schedule.NewBasicBlock();
+    BasicBlock* E = schedule.NewBasicBlock();
+    BasicBlock* F = schedule.NewBasicBlock();
+    BasicBlock* G = schedule.end();
+
+    schedule.AddSuccessorForTesting(A, B);
+    schedule.AddSuccessorForTesting(B, C);
+    schedule.AddSuccessorForTesting(C, D);
+    schedule.AddSuccessorForTesting(D, E);
+    schedule.AddSuccessorForTesting(E, F);
+    schedule.AddSuccessorForTesting(F, B);
+    schedule.AddSuccessorForTesting(B, G);
+
+    // Throw in extra backedges from time to time.
+    if (i == 1) schedule.AddSuccessorForTesting(B, B);
+    if (i == 2) schedule.AddSuccessorForTesting(C, B);
+    if (i == 3) schedule.AddSuccessorForTesting(D, B);
+    if (i == 4) schedule.AddSuccessorForTesting(E, B);
+    if (i == 5) schedule.AddSuccessorForTesting(F, B);
+
+    // Throw in extra loop exits from time to time.
+    if (i == 6) schedule.AddSuccessorForTesting(B, G);
+    if (i == 7) schedule.AddSuccessorForTesting(C, G);
+    if (i == 8) schedule.AddSuccessorForTesting(D, G);
+    if (i == 9) schedule.AddSuccessorForTesting(E, G);
+    if (i == 10) schedule.AddSuccessorForTesting(F, G);
+
+    BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+    CheckRPONumbers(order, 7, true);
+    BasicBlock* loop[] = {B, C, D, E, F};
+    CheckLoop(order, loop, 5);
+  }
+}
+
+TEST_F(SchedulerRPOTest, LoopNest1) {
+  Schedule schedule(zone());
+
+  BasicBlock* A = schedule.start();
+  BasicBlock* B = schedule.NewBasicBlock();
+  BasicBlock* C = schedule.NewBasicBlock();
+  BasicBlock* D = schedule.NewBasicBlock();
+  BasicBlock* E = schedule.NewBasicBlock();
+  BasicBlock* F = schedule.end();
+
+  schedule.AddSuccessorForTesting(A, B);
+  schedule.AddSuccessorForTesting(B, C);
+  schedule.AddSuccessorForTesting(C, D);
+  schedule.AddSuccessorForTesting(D, C);
+  schedule.AddSuccessorForTesting(D, E);
+  schedule.AddSuccessorForTesting(E, B);
+  schedule.AddSuccessorForTesting(E, F);
+
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 6, true);
+  BasicBlock* loop1[] = {B, C, D, E};
+  CheckLoop(order, loop1, 4);
+
+  BasicBlock* loop2[] = {C, D};
+  CheckLoop(order, loop2, 2);
+}
+
+TEST_F(SchedulerRPOTest, LoopNest2) {
+  Schedule schedule(zone());
+
+  BasicBlock* A = schedule.start();
+  BasicBlock* B = schedule.NewBasicBlock();
+  BasicBlock* C = schedule.NewBasicBlock();
+  BasicBlock* D = schedule.NewBasicBlock();
+  BasicBlock* E = schedule.NewBasicBlock();
+  BasicBlock* F = schedule.NewBasicBlock();
+  BasicBlock* G = schedule.NewBasicBlock();
+  BasicBlock* H = schedule.end();
+
+  schedule.AddSuccessorForTesting(A, B);
+  schedule.AddSuccessorForTesting(B, C);
+  schedule.AddSuccessorForTesting(C, D);
+  schedule.AddSuccessorForTesting(D, E);
+  schedule.AddSuccessorForTesting(E, F);
+  schedule.AddSuccessorForTesting(F, G);
+  schedule.AddSuccessorForTesting(G, H);
+
+  schedule.AddSuccessorForTesting(E, D);
+  schedule.AddSuccessorForTesting(F, C);
+  schedule.AddSuccessorForTesting(G, B);
+
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 8, true);
+  BasicBlock* loop1[] = {B, C, D, E, F, G};
+  CheckLoop(order, loop1, 6);
+
+  BasicBlock* loop2[] = {C, D, E, F};
+  CheckLoop(order, loop2, 4);
+
+  BasicBlock* loop3[] = {D, E};
+  CheckLoop(order, loop3, 2);
+}
+
+TEST_F(SchedulerRPOTest, LoopFollow1) {
+  Schedule schedule(zone());
+
+  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
+  base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
+
+  BasicBlock* A = schedule.start();
+  BasicBlock* E = schedule.end();
+
+  schedule.AddSuccessorForTesting(A, loop1->header());
+  schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
+  schedule.AddSuccessorForTesting(loop2->last(), E);
+
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+
+  EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+  CheckLoop(order, loop1->nodes, loop1->count);
+  CheckLoop(order, loop2->nodes, loop2->count);
+}
+
+TEST_F(SchedulerRPOTest, LoopFollow2) {
+  Schedule schedule(zone());
+
+  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
+  base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
+
+  BasicBlock* A = schedule.start();
+  BasicBlock* S = schedule.NewBasicBlock();
+  BasicBlock* E = schedule.end();
+
+  schedule.AddSuccessorForTesting(A, loop1->header());
+  schedule.AddSuccessorForTesting(loop1->header(), S);
+  schedule.AddSuccessorForTesting(S, loop2->header());
+  schedule.AddSuccessorForTesting(loop2->last(), E);
+
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+
+  EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+  CheckLoop(order, loop1->nodes, loop1->count);
+  CheckLoop(order, loop2->nodes, loop2->count);
+}
+
+TEST_F(SchedulerRPOTest, LoopFollowN) {
+  for (int size = 1; size < 5; size++) {
+    for (int exit = 0; exit < size; exit++) {
+      Schedule schedule(zone());
+      base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+      base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size));
+      BasicBlock* A = schedule.start();
+      BasicBlock* E = schedule.end();
+
+      schedule.AddSuccessorForTesting(A, loop1->header());
+      schedule.AddSuccessorForTesting(loop1->nodes[exit], loop2->header());
+      schedule.AddSuccessorForTesting(loop2->nodes[exit], E);
+      BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+
+      EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+      CheckLoop(order, loop1->nodes, loop1->count);
+      CheckLoop(order, loop2->nodes, loop2->count);
+    }
+  }
+}
+
+TEST_F(SchedulerRPOTest, NestedLoopFollow1) {
+  Schedule schedule(zone());
+
+  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
+  base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
+
+  BasicBlock* A = schedule.start();
+  BasicBlock* B = schedule.NewBasicBlock();
+  BasicBlock* C = schedule.NewBasicBlock();
+  BasicBlock* E = schedule.end();
+
+  schedule.AddSuccessorForTesting(A, B);
+  schedule.AddSuccessorForTesting(B, loop1->header());
+  schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
+  schedule.AddSuccessorForTesting(loop2->last(), C);
+  schedule.AddSuccessorForTesting(C, E);
+  schedule.AddSuccessorForTesting(C, B);
+
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+
+  EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+  CheckLoop(order, loop1->nodes, loop1->count);
+  CheckLoop(order, loop2->nodes, loop2->count);
+
+  BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C};
+  CheckLoop(order, loop3, 4);
+}
+
+TEST_F(SchedulerRPOTest, LoopBackedges1) {
+  int size = 8;
+  for (int i = 0; i < size; i++) {
+    for (int j = 0; j < size; j++) {
+      Schedule schedule(zone());
+      BasicBlock* A = schedule.start();
+      BasicBlock* E = schedule.end();
+
+      base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+      schedule.AddSuccessorForTesting(A, loop1->header());
+      schedule.AddSuccessorForTesting(loop1->last(), E);
+
+      schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
+      schedule.AddSuccessorForTesting(loop1->nodes[j], E);
+
+      BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+      CheckRPONumbers(order, schedule.BasicBlockCount(), true);
+      CheckLoop(order, loop1->nodes, loop1->count);
+    }
+  }
+}
+
+TEST_F(SchedulerRPOTest, LoopOutedges1) {
+  int size = 8;
+  for (int i = 0; i < size; i++) {
+    for (int j = 0; j < size; j++) {
+      Schedule schedule(zone());
+      BasicBlock* A = schedule.start();
+      BasicBlock* D = schedule.NewBasicBlock();
+      BasicBlock* E = schedule.end();
+
+      base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+      schedule.AddSuccessorForTesting(A, loop1->header());
+      schedule.AddSuccessorForTesting(loop1->last(), E);
+
+      schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
+      schedule.AddSuccessorForTesting(loop1->nodes[j], D);
+      schedule.AddSuccessorForTesting(D, E);
+
+      BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+      CheckRPONumbers(order, schedule.BasicBlockCount(), true);
+      CheckLoop(order, loop1->nodes, loop1->count);
+    }
+  }
+}
+
+TEST_F(SchedulerRPOTest, LoopOutedges2) {
+  int size = 8;
+  for (int i = 0; i < size; i++) {
+    Schedule schedule(zone());
+    BasicBlock* A = schedule.start();
+    BasicBlock* E = schedule.end();
+
+    base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+    schedule.AddSuccessorForTesting(A, loop1->header());
+    schedule.AddSuccessorForTesting(loop1->last(), E);
+
+    for (int j = 0; j < size; j++) {
+      BasicBlock* O = schedule.NewBasicBlock();
+      schedule.AddSuccessorForTesting(loop1->nodes[j], O);
+      schedule.AddSuccessorForTesting(O, E);
+    }
+
+    BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+    CheckRPONumbers(order, schedule.BasicBlockCount(), true);
+    CheckLoop(order, loop1->nodes, loop1->count);
+  }
+}
+
+TEST_F(SchedulerRPOTest, LoopOutloops1) {
+  int size = 8;
+  for (int i = 0; i < size; i++) {
+    Schedule schedule(zone());
+    BasicBlock* A = schedule.start();
+    BasicBlock* E = schedule.end();
+    base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+    schedule.AddSuccessorForTesting(A, loop1->header());
+    schedule.AddSuccessorForTesting(loop1->last(), E);
+
+    TestLoop** loopN = new TestLoop*[size];
+    for (int j = 0; j < size; j++) {
+      loopN[j] = CreateLoop(&schedule, 2);
+      schedule.AddSuccessorForTesting(loop1->nodes[j], loopN[j]->header());
+      schedule.AddSuccessorForTesting(loopN[j]->last(), E);
+    }
+
+    BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+    CheckRPONumbers(order, schedule.BasicBlockCount(), true);
+    CheckLoop(order, loop1->nodes, loop1->count);
+
+    for (int j = 0; j < size; j++) {
+      CheckLoop(order, loopN[j]->nodes, loopN[j]->count);
+      delete loopN[j];
+    }
+    delete[] loopN;
+  }
+}
+
+TEST_F(SchedulerRPOTest, LoopMultibackedge) {
+  Schedule schedule(zone());
+
+  BasicBlock* A = schedule.start();
+  BasicBlock* B = schedule.NewBasicBlock();
+  BasicBlock* C = schedule.NewBasicBlock();
+  BasicBlock* D = schedule.NewBasicBlock();
+  BasicBlock* E = schedule.NewBasicBlock();
+
+  schedule.AddSuccessorForTesting(A, B);
+  schedule.AddSuccessorForTesting(B, C);
+  schedule.AddSuccessorForTesting(B, D);
+  schedule.AddSuccessorForTesting(B, E);
+  schedule.AddSuccessorForTesting(C, B);
+  schedule.AddSuccessorForTesting(D, B);
+  schedule.AddSuccessorForTesting(E, B);
+
+  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+  CheckRPONumbers(order, 5, true);
+
+  BasicBlock* loop1[] = {B, C, D, E};
+  CheckLoop(order, loop1, 4);
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/compiler/scheduler-unittest.cc b/test/unittests/compiler/scheduler-unittest.cc
index 523c8ce..6cf0734 100644
--- a/test/unittests/compiler/scheduler-unittest.cc
+++ b/test/unittests/compiler/scheduler-unittest.cc
@@ -71,67 +71,6 @@
 };
 
 
-class SchedulerRPOTest : public SchedulerTest {
- public:
-  SchedulerRPOTest() {}
-
-  // TODO(titzer): pull RPO tests out to their own file.
-  void CheckRPONumbers(BasicBlockVector* order, size_t expected,
-                       bool loops_allowed) {
-    CHECK(expected == order->size());
-    for (int i = 0; i < static_cast<int>(order->size()); i++) {
-      CHECK(order->at(i)->rpo_number() == i);
-      if (!loops_allowed) {
-        CHECK(!order->at(i)->loop_end());
-        CHECK(!order->at(i)->loop_header());
-      }
-    }
-  }
-
-  void CheckLoop(BasicBlockVector* order, BasicBlock** blocks, int body_size) {
-    BasicBlock* header = blocks[0];
-    BasicBlock* end = header->loop_end();
-    CHECK(end);
-    CHECK_GT(end->rpo_number(), 0);
-    CHECK_EQ(body_size, end->rpo_number() - header->rpo_number());
-    for (int i = 0; i < body_size; i++) {
-      CHECK_GE(blocks[i]->rpo_number(), header->rpo_number());
-      CHECK_LT(blocks[i]->rpo_number(), end->rpo_number());
-      CHECK(header->LoopContains(blocks[i]));
-      CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header);
-    }
-    if (header->rpo_number() > 0) {
-      CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header);
-    }
-    if (end->rpo_number() < static_cast<int>(order->size())) {
-      CHECK_NE(order->at(end->rpo_number())->loop_header(), header);
-    }
-  }
-
-  struct TestLoop {
-    int count;
-    BasicBlock** nodes;
-    BasicBlock* header() { return nodes[0]; }
-    BasicBlock* last() { return nodes[count - 1]; }
-    ~TestLoop() { delete[] nodes; }
-  };
-
-  TestLoop* CreateLoop(Schedule* schedule, int count) {
-    TestLoop* loop = new TestLoop();
-    loop->count = count;
-    loop->nodes = new BasicBlock* [count];
-    for (int i = 0; i < count; i++) {
-      loop->nodes[i] = schedule->NewBasicBlock();
-      if (i > 0) {
-        schedule->AddSuccessorForTesting(loop->nodes[i - 1], loop->nodes[i]);
-      }
-    }
-    schedule->AddSuccessorForTesting(loop->nodes[count - 1], loop->nodes[0]);
-    return loop;
-  }
-};
-
-
 namespace {
 
 const Operator kHeapConstant(IrOpcode::kHeapConstant, Operator::kPure,
@@ -146,491 +85,6 @@
 }  // namespace
 
 
-// -----------------------------------------------------------------------------
-// Special reverse-post-order block ordering.
-
-
-TEST_F(SchedulerRPOTest, Degenerate1) {
-  Schedule schedule(zone());
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 1, false);
-  EXPECT_EQ(schedule.start(), order->at(0));
-}
-
-
-TEST_F(SchedulerRPOTest, Degenerate2) {
-  Schedule schedule(zone());
-
-  schedule.AddGoto(schedule.start(), schedule.end());
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 2, false);
-  EXPECT_EQ(schedule.start(), order->at(0));
-  EXPECT_EQ(schedule.end(), order->at(1));
-}
-
-
-TEST_F(SchedulerRPOTest, Line) {
-  for (int i = 0; i < 10; i++) {
-    Schedule schedule(zone());
-
-    BasicBlock* last = schedule.start();
-    for (int j = 0; j < i; j++) {
-      BasicBlock* block = schedule.NewBasicBlock();
-      block->set_deferred(i & 1);
-      schedule.AddGoto(last, block);
-      last = block;
-    }
-    BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-    CheckRPONumbers(order, 1 + i, false);
-
-    for (size_t i = 0; i < schedule.BasicBlockCount(); i++) {
-      BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i));
-      if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) {
-        EXPECT_EQ(block->rpo_number() + 1, block->SuccessorAt(0)->rpo_number());
-      }
-    }
-  }
-}
-
-
-TEST_F(SchedulerRPOTest, SelfLoop) {
-  Schedule schedule(zone());
-  schedule.AddSuccessorForTesting(schedule.start(), schedule.start());
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 1, true);
-  BasicBlock* loop[] = {schedule.start()};
-  CheckLoop(order, loop, 1);
-}
-
-
-TEST_F(SchedulerRPOTest, EntryLoop) {
-  Schedule schedule(zone());
-  BasicBlock* body = schedule.NewBasicBlock();
-  schedule.AddSuccessorForTesting(schedule.start(), body);
-  schedule.AddSuccessorForTesting(body, schedule.start());
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 2, true);
-  BasicBlock* loop[] = {schedule.start(), body};
-  CheckLoop(order, loop, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, EndLoop) {
-  Schedule schedule(zone());
-  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
-  schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 3, true);
-  CheckLoop(order, loop1->nodes, loop1->count);
-}
-
-
-TEST_F(SchedulerRPOTest, EndLoopNested) {
-  Schedule schedule(zone());
-  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
-  schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
-  schedule.AddSuccessorForTesting(loop1->last(), schedule.start());
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 3, true);
-  CheckLoop(order, loop1->nodes, loop1->count);
-}
-
-
-TEST_F(SchedulerRPOTest, Diamond) {
-  Schedule schedule(zone());
-
-  BasicBlock* A = schedule.start();
-  BasicBlock* B = schedule.NewBasicBlock();
-  BasicBlock* C = schedule.NewBasicBlock();
-  BasicBlock* D = schedule.end();
-
-  schedule.AddSuccessorForTesting(A, B);
-  schedule.AddSuccessorForTesting(A, C);
-  schedule.AddSuccessorForTesting(B, D);
-  schedule.AddSuccessorForTesting(C, D);
-
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 4, false);
-
-  EXPECT_EQ(0, A->rpo_number());
-  EXPECT_THAT(B->rpo_number(), AnyOf(1, 2));
-  EXPECT_THAT(C->rpo_number(), AnyOf(1, 2));
-  EXPECT_EQ(3, D->rpo_number());
-}
-
-
-TEST_F(SchedulerRPOTest, Loop1) {
-  Schedule schedule(zone());
-
-  BasicBlock* A = schedule.start();
-  BasicBlock* B = schedule.NewBasicBlock();
-  BasicBlock* C = schedule.NewBasicBlock();
-  BasicBlock* D = schedule.end();
-
-  schedule.AddSuccessorForTesting(A, B);
-  schedule.AddSuccessorForTesting(B, C);
-  schedule.AddSuccessorForTesting(C, B);
-  schedule.AddSuccessorForTesting(C, D);
-
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 4, true);
-  BasicBlock* loop[] = {B, C};
-  CheckLoop(order, loop, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, Loop2) {
-  Schedule schedule(zone());
-
-  BasicBlock* A = schedule.start();
-  BasicBlock* B = schedule.NewBasicBlock();
-  BasicBlock* C = schedule.NewBasicBlock();
-  BasicBlock* D = schedule.end();
-
-  schedule.AddSuccessorForTesting(A, B);
-  schedule.AddSuccessorForTesting(B, C);
-  schedule.AddSuccessorForTesting(C, B);
-  schedule.AddSuccessorForTesting(B, D);
-
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 4, true);
-  BasicBlock* loop[] = {B, C};
-  CheckLoop(order, loop, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopN) {
-  for (int i = 0; i < 11; i++) {
-    Schedule schedule(zone());
-    BasicBlock* A = schedule.start();
-    BasicBlock* B = schedule.NewBasicBlock();
-    BasicBlock* C = schedule.NewBasicBlock();
-    BasicBlock* D = schedule.NewBasicBlock();
-    BasicBlock* E = schedule.NewBasicBlock();
-    BasicBlock* F = schedule.NewBasicBlock();
-    BasicBlock* G = schedule.end();
-
-    schedule.AddSuccessorForTesting(A, B);
-    schedule.AddSuccessorForTesting(B, C);
-    schedule.AddSuccessorForTesting(C, D);
-    schedule.AddSuccessorForTesting(D, E);
-    schedule.AddSuccessorForTesting(E, F);
-    schedule.AddSuccessorForTesting(F, B);
-    schedule.AddSuccessorForTesting(B, G);
-
-    // Throw in extra backedges from time to time.
-    if (i == 1) schedule.AddSuccessorForTesting(B, B);
-    if (i == 2) schedule.AddSuccessorForTesting(C, B);
-    if (i == 3) schedule.AddSuccessorForTesting(D, B);
-    if (i == 4) schedule.AddSuccessorForTesting(E, B);
-    if (i == 5) schedule.AddSuccessorForTesting(F, B);
-
-    // Throw in extra loop exits from time to time.
-    if (i == 6) schedule.AddSuccessorForTesting(B, G);
-    if (i == 7) schedule.AddSuccessorForTesting(C, G);
-    if (i == 8) schedule.AddSuccessorForTesting(D, G);
-    if (i == 9) schedule.AddSuccessorForTesting(E, G);
-    if (i == 10) schedule.AddSuccessorForTesting(F, G);
-
-    BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-    CheckRPONumbers(order, 7, true);
-    BasicBlock* loop[] = {B, C, D, E, F};
-    CheckLoop(order, loop, 5);
-  }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopNest1) {
-  Schedule schedule(zone());
-
-  BasicBlock* A = schedule.start();
-  BasicBlock* B = schedule.NewBasicBlock();
-  BasicBlock* C = schedule.NewBasicBlock();
-  BasicBlock* D = schedule.NewBasicBlock();
-  BasicBlock* E = schedule.NewBasicBlock();
-  BasicBlock* F = schedule.end();
-
-  schedule.AddSuccessorForTesting(A, B);
-  schedule.AddSuccessorForTesting(B, C);
-  schedule.AddSuccessorForTesting(C, D);
-  schedule.AddSuccessorForTesting(D, C);
-  schedule.AddSuccessorForTesting(D, E);
-  schedule.AddSuccessorForTesting(E, B);
-  schedule.AddSuccessorForTesting(E, F);
-
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 6, true);
-  BasicBlock* loop1[] = {B, C, D, E};
-  CheckLoop(order, loop1, 4);
-
-  BasicBlock* loop2[] = {C, D};
-  CheckLoop(order, loop2, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopNest2) {
-  Schedule schedule(zone());
-
-  BasicBlock* A = schedule.start();
-  BasicBlock* B = schedule.NewBasicBlock();
-  BasicBlock* C = schedule.NewBasicBlock();
-  BasicBlock* D = schedule.NewBasicBlock();
-  BasicBlock* E = schedule.NewBasicBlock();
-  BasicBlock* F = schedule.NewBasicBlock();
-  BasicBlock* G = schedule.NewBasicBlock();
-  BasicBlock* H = schedule.end();
-
-  schedule.AddSuccessorForTesting(A, B);
-  schedule.AddSuccessorForTesting(B, C);
-  schedule.AddSuccessorForTesting(C, D);
-  schedule.AddSuccessorForTesting(D, E);
-  schedule.AddSuccessorForTesting(E, F);
-  schedule.AddSuccessorForTesting(F, G);
-  schedule.AddSuccessorForTesting(G, H);
-
-  schedule.AddSuccessorForTesting(E, D);
-  schedule.AddSuccessorForTesting(F, C);
-  schedule.AddSuccessorForTesting(G, B);
-
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 8, true);
-  BasicBlock* loop1[] = {B, C, D, E, F, G};
-  CheckLoop(order, loop1, 6);
-
-  BasicBlock* loop2[] = {C, D, E, F};
-  CheckLoop(order, loop2, 4);
-
-  BasicBlock* loop3[] = {D, E};
-  CheckLoop(order, loop3, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopFollow1) {
-  Schedule schedule(zone());
-
-  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
-  base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
-
-  BasicBlock* A = schedule.start();
-  BasicBlock* E = schedule.end();
-
-  schedule.AddSuccessorForTesting(A, loop1->header());
-  schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
-  schedule.AddSuccessorForTesting(loop2->last(), E);
-
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-
-  EXPECT_EQ(schedule.BasicBlockCount(), order->size());
-  CheckLoop(order, loop1->nodes, loop1->count);
-  CheckLoop(order, loop2->nodes, loop2->count);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopFollow2) {
-  Schedule schedule(zone());
-
-  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
-  base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
-
-  BasicBlock* A = schedule.start();
-  BasicBlock* S = schedule.NewBasicBlock();
-  BasicBlock* E = schedule.end();
-
-  schedule.AddSuccessorForTesting(A, loop1->header());
-  schedule.AddSuccessorForTesting(loop1->header(), S);
-  schedule.AddSuccessorForTesting(S, loop2->header());
-  schedule.AddSuccessorForTesting(loop2->last(), E);
-
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-
-  EXPECT_EQ(schedule.BasicBlockCount(), order->size());
-  CheckLoop(order, loop1->nodes, loop1->count);
-  CheckLoop(order, loop2->nodes, loop2->count);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopFollowN) {
-  for (int size = 1; size < 5; size++) {
-    for (int exit = 0; exit < size; exit++) {
-      Schedule schedule(zone());
-      base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
-      base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size));
-      BasicBlock* A = schedule.start();
-      BasicBlock* E = schedule.end();
-
-      schedule.AddSuccessorForTesting(A, loop1->header());
-      schedule.AddSuccessorForTesting(loop1->nodes[exit], loop2->header());
-      schedule.AddSuccessorForTesting(loop2->nodes[exit], E);
-      BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-
-      EXPECT_EQ(schedule.BasicBlockCount(), order->size());
-      CheckLoop(order, loop1->nodes, loop1->count);
-      CheckLoop(order, loop2->nodes, loop2->count);
-    }
-  }
-}
-
-
-TEST_F(SchedulerRPOTest, NestedLoopFollow1) {
-  Schedule schedule(zone());
-
-  base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
-  base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
-
-  BasicBlock* A = schedule.start();
-  BasicBlock* B = schedule.NewBasicBlock();
-  BasicBlock* C = schedule.NewBasicBlock();
-  BasicBlock* E = schedule.end();
-
-  schedule.AddSuccessorForTesting(A, B);
-  schedule.AddSuccessorForTesting(B, loop1->header());
-  schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
-  schedule.AddSuccessorForTesting(loop2->last(), C);
-  schedule.AddSuccessorForTesting(C, E);
-  schedule.AddSuccessorForTesting(C, B);
-
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-
-  EXPECT_EQ(schedule.BasicBlockCount(), order->size());
-  CheckLoop(order, loop1->nodes, loop1->count);
-  CheckLoop(order, loop2->nodes, loop2->count);
-
-  BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C};
-  CheckLoop(order, loop3, 4);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopBackedges1) {
-  int size = 8;
-  for (int i = 0; i < size; i++) {
-    for (int j = 0; j < size; j++) {
-      Schedule schedule(zone());
-      BasicBlock* A = schedule.start();
-      BasicBlock* E = schedule.end();
-
-      base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
-      schedule.AddSuccessorForTesting(A, loop1->header());
-      schedule.AddSuccessorForTesting(loop1->last(), E);
-
-      schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
-      schedule.AddSuccessorForTesting(loop1->nodes[j], E);
-
-      BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-      CheckRPONumbers(order, schedule.BasicBlockCount(), true);
-      CheckLoop(order, loop1->nodes, loop1->count);
-    }
-  }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopOutedges1) {
-  int size = 8;
-  for (int i = 0; i < size; i++) {
-    for (int j = 0; j < size; j++) {
-      Schedule schedule(zone());
-      BasicBlock* A = schedule.start();
-      BasicBlock* D = schedule.NewBasicBlock();
-      BasicBlock* E = schedule.end();
-
-      base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
-      schedule.AddSuccessorForTesting(A, loop1->header());
-      schedule.AddSuccessorForTesting(loop1->last(), E);
-
-      schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
-      schedule.AddSuccessorForTesting(loop1->nodes[j], D);
-      schedule.AddSuccessorForTesting(D, E);
-
-      BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-      CheckRPONumbers(order, schedule.BasicBlockCount(), true);
-      CheckLoop(order, loop1->nodes, loop1->count);
-    }
-  }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopOutedges2) {
-  int size = 8;
-  for (int i = 0; i < size; i++) {
-    Schedule schedule(zone());
-    BasicBlock* A = schedule.start();
-    BasicBlock* E = schedule.end();
-
-    base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
-    schedule.AddSuccessorForTesting(A, loop1->header());
-    schedule.AddSuccessorForTesting(loop1->last(), E);
-
-    for (int j = 0; j < size; j++) {
-      BasicBlock* O = schedule.NewBasicBlock();
-      schedule.AddSuccessorForTesting(loop1->nodes[j], O);
-      schedule.AddSuccessorForTesting(O, E);
-    }
-
-    BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-    CheckRPONumbers(order, schedule.BasicBlockCount(), true);
-    CheckLoop(order, loop1->nodes, loop1->count);
-  }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopOutloops1) {
-  int size = 8;
-  for (int i = 0; i < size; i++) {
-    Schedule schedule(zone());
-    BasicBlock* A = schedule.start();
-    BasicBlock* E = schedule.end();
-    base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
-    schedule.AddSuccessorForTesting(A, loop1->header());
-    schedule.AddSuccessorForTesting(loop1->last(), E);
-
-    TestLoop** loopN = new TestLoop* [size];
-    for (int j = 0; j < size; j++) {
-      loopN[j] = CreateLoop(&schedule, 2);
-      schedule.AddSuccessorForTesting(loop1->nodes[j], loopN[j]->header());
-      schedule.AddSuccessorForTesting(loopN[j]->last(), E);
-    }
-
-    BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-    CheckRPONumbers(order, schedule.BasicBlockCount(), true);
-    CheckLoop(order, loop1->nodes, loop1->count);
-
-    for (int j = 0; j < size; j++) {
-      CheckLoop(order, loopN[j]->nodes, loopN[j]->count);
-      delete loopN[j];
-    }
-    delete[] loopN;
-  }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopMultibackedge) {
-  Schedule schedule(zone());
-
-  BasicBlock* A = schedule.start();
-  BasicBlock* B = schedule.NewBasicBlock();
-  BasicBlock* C = schedule.NewBasicBlock();
-  BasicBlock* D = schedule.NewBasicBlock();
-  BasicBlock* E = schedule.NewBasicBlock();
-
-  schedule.AddSuccessorForTesting(A, B);
-  schedule.AddSuccessorForTesting(B, C);
-  schedule.AddSuccessorForTesting(B, D);
-  schedule.AddSuccessorForTesting(B, E);
-  schedule.AddSuccessorForTesting(C, B);
-  schedule.AddSuccessorForTesting(D, B);
-  schedule.AddSuccessorForTesting(E, B);
-
-  BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-  CheckRPONumbers(order, 5, true);
-
-  BasicBlock* loop1[] = {B, C, D, E};
-  CheckLoop(order, loop1, 4);
-}
-
-
-// -----------------------------------------------------------------------------
-// Graph end-to-end scheduling.
-
-
 TEST_F(SchedulerTest, BuildScheduleEmpty) {
   graph()->SetStart(graph()->NewNode(common()->Start(0)));
   graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
diff --git a/test/unittests/compiler/simplified-operator-unittest.cc b/test/unittests/compiler/simplified-operator-unittest.cc
index 871189a..bd8509f 100644
--- a/test/unittests/compiler/simplified-operator-unittest.cc
+++ b/test/unittests/compiler/simplified-operator-unittest.cc
@@ -6,7 +6,7 @@
 #include "src/compiler/operator.h"
 #include "src/compiler/operator-properties.h"
 #include "src/compiler/simplified-operator.h"
-#include "src/types-inl.h"
+#include "src/types.h"
 #include "test/unittests/test-utils.h"
 
 namespace v8 {
@@ -65,6 +65,8 @@
     PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
     PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
     PURE(ChangeBitToBool, Operator::kNoProperties, 1),
+    PURE(ObjectIsNumber, Operator::kNoProperties, 1),
+    PURE(ObjectIsReceiver, Operator::kNoProperties, 1),
     PURE(ObjectIsSmi, Operator::kNoProperties, 1)
 #undef PURE
 };
diff --git a/test/unittests/compiler/typer-unittest.cc b/test/unittests/compiler/typer-unittest.cc
index 6e4d4d5..9d664a6 100644
--- a/test/unittests/compiler/typer-unittest.cc
+++ b/test/unittests/compiler/typer-unittest.cc
@@ -49,7 +49,7 @@
     }
   }
 
-  Types<Type, Type*, Zone> types_;
+  Types types_;
   JSOperatorBuilder javascript_;
   BinaryOperationHints const hints_ = BinaryOperationHints::Any();
   Node* context_node_;
@@ -115,7 +115,7 @@
     return result;
   }
 
-  double RandomInt(Type::RangeType* range) {
+  double RandomInt(RangeType* range) {
     return RandomInt(range->Min(), range->Max());
   }
 
@@ -149,12 +149,12 @@
   void TestBinaryArithOp(const Operator* op, BinaryFunction opfun) {
     TestBinaryArithOpCloseToZero(op, opfun, 8);
     for (int i = 0; i < 100; ++i) {
-      Type::RangeType* r1 = RandomRange()->AsRange();
-      Type::RangeType* r2 = RandomRange()->AsRange();
+      Type* r1 = RandomRange();
+      Type* r2 = RandomRange();
       Type* expected_type = TypeBinaryOp(op, r1, r2);
       for (int i = 0; i < 10; i++) {
-        double x1 = RandomInt(r1);
-        double x2 = RandomInt(r2);
+        double x1 = RandomInt(r1->AsRange());
+        double x2 = RandomInt(r2->AsRange());
         double result_value = opfun(x1, x2);
         Type* result_type = Type::Constant(
             isolate()->factory()->NewNumber(result_value), zone());
@@ -166,12 +166,12 @@
   template <class BinaryFunction>
   void TestBinaryCompareOp(const Operator* op, BinaryFunction opfun) {
     for (int i = 0; i < 100; ++i) {
-      Type::RangeType* r1 = RandomRange()->AsRange();
-      Type::RangeType* r2 = RandomRange()->AsRange();
+      Type* r1 = RandomRange();
+      Type* r2 = RandomRange();
       Type* expected_type = TypeBinaryOp(op, r1, r2);
       for (int i = 0; i < 10; i++) {
-        double x1 = RandomInt(r1);
-        double x2 = RandomInt(r2);
+        double x1 = RandomInt(r1->AsRange());
+        double x2 = RandomInt(r2->AsRange());
         bool result_value = opfun(x1, x2);
         Type* result_type =
             Type::Constant(result_value ? isolate()->factory()->true_value()
@@ -185,12 +185,12 @@
   template <class BinaryFunction>
   void TestBinaryBitOp(const Operator* op, BinaryFunction opfun) {
     for (int i = 0; i < 100; ++i) {
-      Type::RangeType* r1 = RandomRange(true)->AsRange();
-      Type::RangeType* r2 = RandomRange(true)->AsRange();
+      Type* r1 = RandomRange(true);
+      Type* r2 = RandomRange(true);
       Type* expected_type = TypeBinaryOp(op, r1, r2);
       for (int i = 0; i < 10; i++) {
-        int32_t x1 = static_cast<int32_t>(RandomInt(r1));
-        int32_t x2 = static_cast<int32_t>(RandomInt(r2));
+        int32_t x1 = static_cast<int32_t>(RandomInt(r1->AsRange()));
+        int32_t x2 = static_cast<int32_t>(RandomInt(r2->AsRange()));
         double result_value = opfun(x1, x2);
         Type* result_type = Type::Constant(
             isolate()->factory()->NewNumber(result_value), zone());
@@ -240,109 +240,72 @@
 
 
 TEST_F(TyperTest, TypeJSAdd) {
-  TestBinaryArithOp(javascript_.Add(LanguageMode::SLOPPY, hints_),
-                    std::plus<double>());
-  TestBinaryArithOp(javascript_.Add(LanguageMode::STRONG, hints_),
-                    std::plus<double>());
+  TestBinaryArithOp(javascript_.Add(hints_), std::plus<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSSubtract) {
-  TestBinaryArithOp(javascript_.Subtract(LanguageMode::SLOPPY, hints_),
-                    std::minus<double>());
-  TestBinaryArithOp(javascript_.Subtract(LanguageMode::STRONG, hints_),
-                    std::minus<double>());
+  TestBinaryArithOp(javascript_.Subtract(hints_), std::minus<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSMultiply) {
-  TestBinaryArithOp(javascript_.Multiply(LanguageMode::SLOPPY, hints_),
-                    std::multiplies<double>());
-  TestBinaryArithOp(javascript_.Multiply(LanguageMode::STRONG, hints_),
-                    std::multiplies<double>());
+  TestBinaryArithOp(javascript_.Multiply(hints_), std::multiplies<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSDivide) {
-  TestBinaryArithOp(javascript_.Divide(LanguageMode::SLOPPY, hints_),
-                    std::divides<double>());
-  TestBinaryArithOp(javascript_.Divide(LanguageMode::STRONG, hints_),
-                    std::divides<double>());
+  TestBinaryArithOp(javascript_.Divide(hints_), std::divides<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSModulus) {
-  TestBinaryArithOp(javascript_.Modulus(LanguageMode::SLOPPY, hints_), modulo);
-  TestBinaryArithOp(javascript_.Modulus(LanguageMode::STRONG, hints_), modulo);
+  TestBinaryArithOp(javascript_.Modulus(hints_), modulo);
 }
 
 
 TEST_F(TyperTest, TypeJSBitwiseOr) {
-  TestBinaryBitOp(javascript_.BitwiseOr(LanguageMode::SLOPPY, hints_), bit_or);
-  TestBinaryBitOp(javascript_.BitwiseOr(LanguageMode::STRONG, hints_), bit_or);
+  TestBinaryBitOp(javascript_.BitwiseOr(hints_), bit_or);
 }
 
 
 TEST_F(TyperTest, TypeJSBitwiseAnd) {
-  TestBinaryBitOp(javascript_.BitwiseAnd(LanguageMode::SLOPPY, hints_),
-                  bit_and);
-  TestBinaryBitOp(javascript_.BitwiseAnd(LanguageMode::STRONG, hints_),
-                  bit_and);
+  TestBinaryBitOp(javascript_.BitwiseAnd(hints_), bit_and);
 }
 
 
 TEST_F(TyperTest, TypeJSBitwiseXor) {
-  TestBinaryBitOp(javascript_.BitwiseXor(LanguageMode::SLOPPY, hints_),
-                  bit_xor);
-  TestBinaryBitOp(javascript_.BitwiseXor(LanguageMode::STRONG, hints_),
-                  bit_xor);
+  TestBinaryBitOp(javascript_.BitwiseXor(hints_), bit_xor);
 }
 
 
 TEST_F(TyperTest, TypeJSShiftLeft) {
-  TestBinaryBitOp(javascript_.ShiftLeft(LanguageMode::SLOPPY, hints_),
-                  shift_left);
-  TestBinaryBitOp(javascript_.ShiftLeft(LanguageMode::STRONG, hints_),
-                  shift_left);
+  TestBinaryBitOp(javascript_.ShiftLeft(hints_), shift_left);
 }
 
 
 TEST_F(TyperTest, TypeJSShiftRight) {
-  TestBinaryBitOp(javascript_.ShiftRight(LanguageMode::SLOPPY, hints_),
-                  shift_right);
-  TestBinaryBitOp(javascript_.ShiftRight(LanguageMode::STRONG, hints_),
-                  shift_right);
+  TestBinaryBitOp(javascript_.ShiftRight(hints_), shift_right);
 }
 
 
 TEST_F(TyperTest, TypeJSLessThan) {
-  TestBinaryCompareOp(javascript_.LessThan(LanguageMode::SLOPPY),
-                      std::less<double>());
-  TestBinaryCompareOp(javascript_.LessThan(LanguageMode::STRONG),
-                      std::less<double>());
+  TestBinaryCompareOp(javascript_.LessThan(), std::less<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSLessThanOrEqual) {
-  TestBinaryCompareOp(javascript_.LessThanOrEqual(LanguageMode::SLOPPY),
-                      std::less_equal<double>());
-  TestBinaryCompareOp(javascript_.LessThanOrEqual(LanguageMode::STRONG),
-                      std::less_equal<double>());
+  TestBinaryCompareOp(javascript_.LessThanOrEqual(), std::less_equal<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSGreaterThan) {
-  TestBinaryCompareOp(javascript_.GreaterThan(LanguageMode::SLOPPY),
-                      std::greater<double>());
-  TestBinaryCompareOp(javascript_.GreaterThan(LanguageMode::STRONG),
-                      std::greater<double>());
+  TestBinaryCompareOp(javascript_.GreaterThan(), std::greater<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSGreaterThanOrEqual) {
-  TestBinaryCompareOp(javascript_.GreaterThanOrEqual(LanguageMode::SLOPPY),
-                      std::greater_equal<double>());
-  TestBinaryCompareOp(javascript_.GreaterThanOrEqual(LanguageMode::STRONG),
+  TestBinaryCompareOp(javascript_.GreaterThanOrEqual(),
                       std::greater_equal<double>());
 }
 
@@ -381,27 +344,15 @@
 TEST_BINARY_MONOTONICITY(NotEqual)
 TEST_BINARY_MONOTONICITY(StrictEqual)
 TEST_BINARY_MONOTONICITY(StrictNotEqual)
-#undef TEST_BINARY_MONOTONICITY
-
-
-#define TEST_BINARY_MONOTONICITY(name)                              \
-  TEST_F(TyperTest, Monotonicity_##name) {                          \
-    TestBinaryMonotonicity(javascript_.name(LanguageMode::SLOPPY)); \
-    TestBinaryMonotonicity(javascript_.name(LanguageMode::STRONG)); \
-  }
 TEST_BINARY_MONOTONICITY(LessThan)
 TEST_BINARY_MONOTONICITY(GreaterThan)
 TEST_BINARY_MONOTONICITY(LessThanOrEqual)
 TEST_BINARY_MONOTONICITY(GreaterThanOrEqual)
 #undef TEST_BINARY_MONOTONICITY
 
-
-#define TEST_BINARY_MONOTONICITY(name)                                        \
-  TEST_F(TyperTest, Monotonicity_##name) {                                    \
-    TestBinaryMonotonicity(                                                   \
-        javascript_.name(LanguageMode::SLOPPY, BinaryOperationHints::Any())); \
-    TestBinaryMonotonicity(                                                   \
-        javascript_.name(LanguageMode::STRONG, BinaryOperationHints::Any())); \
+#define TEST_BINARY_MONOTONICITY(name)                                     \
+  TEST_F(TyperTest, Monotonicity_##name) {                                 \
+    TestBinaryMonotonicity(javascript_.name(BinaryOperationHints::Any())); \
   }
 TEST_BINARY_MONOTONICITY(BitwiseOr)
 TEST_BINARY_MONOTONICITY(BitwiseXor)
diff --git a/test/unittests/heap/memory-reducer-unittest.cc b/test/unittests/heap/memory-reducer-unittest.cc
index 1088f01..4787bc6 100644
--- a/test/unittests/heap/memory-reducer-unittest.cc
+++ b/test/unittests/heap/memory-reducer-unittest.cc
@@ -74,10 +74,9 @@
   return TimerEvent(time_ms, true, false);
 }
 
-
-MemoryReducer::Event ContextDisposedEvent(double time_ms) {
+MemoryReducer::Event PossibleGarbageEvent(double time_ms) {
   MemoryReducer::Event event;
-  event.type = MemoryReducer::kContextDisposed;
+  event.type = MemoryReducer::kPossibleGarbage;
   event.time_ms = time_ms;
   return event;
 }
@@ -114,7 +113,7 @@
   EXPECT_EQ(0, state1.started_gcs);
   EXPECT_EQ(2, state1.last_gc_time_ms);
 
-  state1 = MemoryReducer::Step(state0, ContextDisposedEvent(0));
+  state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(0));
   EXPECT_EQ(MemoryReducer::kWait, state1.action);
   EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
   EXPECT_EQ(0, state1.started_gcs);
@@ -127,7 +126,7 @@
 
   MemoryReducer::State state0(WaitState(2, 1000.0)), state1(DoneState());
 
-  state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000));
+  state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(2000));
   EXPECT_EQ(MemoryReducer::kWait, state1.action);
   EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
   EXPECT_EQ(state0.started_gcs, state1.started_gcs);
@@ -250,7 +249,7 @@
   EXPECT_EQ(state0.started_gcs, state1.started_gcs);
   EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
 
-  state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000));
+  state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(2000));
   EXPECT_EQ(MemoryReducer::kRun, state1.action);
   EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
   EXPECT_EQ(state0.started_gcs, state1.started_gcs);
diff --git a/test/unittests/heap/slot-set-unittest.cc b/test/unittests/heap/slot-set-unittest.cc
new file mode 100644
index 0000000..3761889
--- /dev/null
+++ b/test/unittests/heap/slot-set-unittest.cc
@@ -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.
+
+#include <limits>
+
+#include "src/globals.h"
+#include "src/heap/slot-set.h"
+#include "src/heap/spaces.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace internal {
+
+TEST(SlotSet, InsertAndLookup1) {
+  SlotSet set;
+  set.SetPageStart(0);
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    EXPECT_FALSE(set.Lookup(i));
+  }
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    set.Insert(i);
+  }
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    EXPECT_TRUE(set.Lookup(i));
+  }
+}
+
+TEST(SlotSet, InsertAndLookup2) {
+  SlotSet set;
+  set.SetPageStart(0);
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    if (i % 7 == 0) {
+      set.Insert(i);
+    }
+  }
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    if (i % 7 == 0) {
+      EXPECT_TRUE(set.Lookup(i));
+    } else {
+      EXPECT_FALSE(set.Lookup(i));
+    }
+  }
+}
+
+TEST(SlotSet, Iterate) {
+  SlotSet set;
+  set.SetPageStart(0);
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    if (i % 7 == 0) {
+      set.Insert(i);
+    }
+  }
+
+  set.Iterate([](Address slot_address) {
+    uintptr_t intaddr = reinterpret_cast<uintptr_t>(slot_address);
+    if (intaddr % 3 == 0) {
+      return SlotSet::KEEP_SLOT;
+    } else {
+      return SlotSet::REMOVE_SLOT;
+    }
+  });
+
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    if (i % 21 == 0) {
+      EXPECT_TRUE(set.Lookup(i));
+    } else {
+      EXPECT_FALSE(set.Lookup(i));
+    }
+  }
+}
+
+TEST(SlotSet, Remove) {
+  SlotSet set;
+  set.SetPageStart(0);
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    if (i % 7 == 0) {
+      set.Insert(i);
+    }
+  }
+
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    if (i % 3 != 0) {
+      set.Remove(i);
+    }
+  }
+
+  for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+    if (i % 21 == 0) {
+      EXPECT_TRUE(set.Lookup(i));
+    } else {
+      EXPECT_FALSE(set.Lookup(i));
+    }
+  }
+}
+
+void CheckRemoveRangeOn(uint32_t start, uint32_t end) {
+  SlotSet set;
+  set.SetPageStart(0);
+  uint32_t first = start == 0 ? 0 : start - kPointerSize;
+  uint32_t last = end == Page::kPageSize ? end - kPointerSize : end;
+  for (uint32_t i = first; i <= last; i += kPointerSize) {
+    set.Insert(i);
+  }
+  set.RemoveRange(start, end);
+  if (first != start) {
+    EXPECT_TRUE(set.Lookup(first));
+  }
+  if (last == end) {
+    EXPECT_TRUE(set.Lookup(last));
+  }
+  for (uint32_t i = start; i < end; i += kPointerSize) {
+    EXPECT_FALSE(set.Lookup(i));
+  }
+}
+
+TEST(SlotSet, RemoveRange) {
+  CheckRemoveRangeOn(0, Page::kPageSize);
+  CheckRemoveRangeOn(1 * kPointerSize, 1023 * kPointerSize);
+  for (uint32_t start = 0; start <= 32; start++) {
+    CheckRemoveRangeOn(start * kPointerSize, (start + 1) * kPointerSize);
+    CheckRemoveRangeOn(start * kPointerSize, (start + 2) * kPointerSize);
+    const uint32_t kEnds[] = {32, 64, 100, 128, 1024, 1500, 2048};
+    for (int i = 0; i < sizeof(kEnds) / sizeof(uint32_t); i++) {
+      for (int k = -3; k <= 3; k++) {
+        uint32_t end = (kEnds[i] + k);
+        if (start < end) {
+          CheckRemoveRangeOn(start * kPointerSize, end * kPointerSize);
+        }
+      }
+    }
+  }
+  SlotSet set;
+  set.SetPageStart(0);
+  set.Insert(Page::kPageSize / 2);
+  set.RemoveRange(0, Page::kPageSize);
+  for (uint32_t i = 0; i < Page::kPageSize; i += kPointerSize) {
+    EXPECT_FALSE(set.Lookup(i));
+  }
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/interpreter/bytecode-array-builder-unittest.cc b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
index 2140aa8..839215f 100644
--- a/test/unittests/interpreter/bytecode-array-builder-unittest.cc
+++ b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
@@ -21,14 +21,16 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
-  BytecodeArrayBuilder builder(isolate(), zone());
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131);
 
-  builder.set_locals_count(200);
-  builder.set_context_count(1);
-  builder.set_parameter_count(0);
-  CHECK_EQ(builder.locals_count(), 200);
+  CHECK_EQ(builder.locals_count(), 131);
   CHECK_EQ(builder.context_count(), 1);
-  CHECK_EQ(builder.fixed_register_count(), 201);
+  CHECK_EQ(builder.fixed_register_count(), 132);
+
+  // Emit argument creation operations.
+  builder.CreateArguments(CreateArgumentsType::kMappedArguments)
+      .CreateArguments(CreateArgumentsType::kUnmappedArguments)
+      .CreateArguments(CreateArgumentsType::kRestParameter);
 
   // Emit constant loads.
   builder.LoadLiteral(Smi::FromInt(0))
@@ -40,32 +42,23 @@
       .LoadTrue()
       .LoadFalse();
 
-  // Emit accumulator transfers. Stores followed by loads to the same register
-  // are not generated. Hence, a dummy instruction in between.
   Register reg(0);
+  Register other(reg.index() + 1);
+  Register wide(128);
+
   builder.LoadAccumulatorWithRegister(reg)
       .LoadNull()
       .StoreAccumulatorInRegister(reg);
 
   // Emit register-register transfer.
-  Register other(1);
   builder.MoveRegister(reg, other);
-
-  // Emit register-register exchanges.
-  Register wide(150);
-  builder.ExchangeRegisters(reg, wide);
-  builder.ExchangeRegisters(wide, reg);
-  Register wider(151);
-  builder.ExchangeRegisters(wide, wider);
+  builder.MoveRegister(reg, wide);
 
   // Emit global load / store operations.
   Factory* factory = isolate()->factory();
   Handle<String> name = factory->NewStringFromStaticChars("var_name");
-  builder.LoadGlobal(name, 1, LanguageMode::SLOPPY,
-                     TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(name, 1, LanguageMode::SLOPPY, TypeofMode::INSIDE_TYPEOF)
-      .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::INSIDE_TYPEOF)
+  builder.LoadGlobal(name, 1, TypeofMode::NOT_INSIDE_TYPEOF)
+      .LoadGlobal(name, 1, TypeofMode::INSIDE_TYPEOF)
       .StoreGlobal(name, 1, LanguageMode::SLOPPY)
       .StoreGlobal(name, 1, LanguageMode::STRICT);
 
@@ -76,12 +69,10 @@
       .StoreContextSlot(reg, 1);
 
   // Emit load / store property operations.
-  builder.LoadNamedProperty(reg, name, 0, LanguageMode::SLOPPY)
-      .LoadKeyedProperty(reg, 0, LanguageMode::SLOPPY)
+  builder.LoadNamedProperty(reg, name, 0)
+      .LoadKeyedProperty(reg, 0)
       .StoreNamedProperty(reg, name, 0, LanguageMode::SLOPPY)
       .StoreKeyedProperty(reg, reg, 0, LanguageMode::SLOPPY)
-      .LoadNamedProperty(reg, name, 0, LanguageMode::STRICT)
-      .LoadKeyedProperty(reg, 0, LanguageMode::STRICT)
       .StoreNamedProperty(reg, name, 0, LanguageMode::STRICT)
       .StoreKeyedProperty(reg, reg, 0, LanguageMode::STRICT);
 
@@ -97,65 +88,64 @@
       false);
   builder.CreateClosure(shared_info, NOT_TENURED);
 
-  // Emit argument creation operations.
-  builder.CreateArguments(CreateArgumentsType::kMappedArguments)
-      .CreateArguments(CreateArgumentsType::kUnmappedArguments);
-
   // Emit literal creation operations.
   builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0)
       .CreateArrayLiteral(factory->NewFixedArray(1), 0, 0)
       .CreateObjectLiteral(factory->NewFixedArray(1), 0, 0);
 
   // Call operations.
-  builder.Call(reg, reg, 0, 0)
-      .Call(reg, reg, 0, 1024)
+  builder.Call(reg, other, 1, 0)
+      .Call(reg, wide, 1, 0)
+      .TailCall(reg, other, 1, 0)
+      .TailCall(reg, wide, 1, 0)
       .CallRuntime(Runtime::kIsArray, reg, 1)
-      .CallRuntimeForPair(Runtime::kLoadLookupSlot, reg, 1, reg)
-      .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1);
+      .CallRuntime(Runtime::kIsArray, wide, 1)
+      .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg, 1, other)
+      .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, wide, 1, other)
+      .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1)
+      .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, wide, 1);
 
   // Emit binary operator invocations.
-  builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::SUB, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::MUL, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::DIV, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::MOD, reg, Strength::WEAK);
+  builder.BinaryOperation(Token::Value::ADD, reg)
+      .BinaryOperation(Token::Value::SUB, reg)
+      .BinaryOperation(Token::Value::MUL, reg)
+      .BinaryOperation(Token::Value::DIV, reg)
+      .BinaryOperation(Token::Value::MOD, reg);
 
   // Emit bitwise operator invocations
-  builder.BinaryOperation(Token::Value::BIT_OR, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::BIT_XOR, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::BIT_AND, reg, Strength::WEAK);
+  builder.BinaryOperation(Token::Value::BIT_OR, reg)
+      .BinaryOperation(Token::Value::BIT_XOR, reg)
+      .BinaryOperation(Token::Value::BIT_AND, reg);
 
   // Emit shift operator invocations
-  builder.BinaryOperation(Token::Value::SHL, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::SAR, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::SHR, reg, Strength::WEAK);
+  builder.BinaryOperation(Token::Value::SHL, reg)
+      .BinaryOperation(Token::Value::SAR, reg)
+      .BinaryOperation(Token::Value::SHR, reg);
 
   // Emit count operatior invocations
-  builder.CountOperation(Token::Value::ADD, Strength::WEAK)
-      .CountOperation(Token::Value::SUB, Strength::WEAK);
+  builder.CountOperation(Token::Value::ADD).CountOperation(Token::Value::SUB);
 
   // Emit unary operator invocations.
   builder.LogicalNot().TypeOf();
 
   // Emit delete
-  builder.Delete(reg, LanguageMode::SLOPPY)
-      .Delete(reg, LanguageMode::STRICT)
-      .DeleteLookupSlot();
+  builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT);
 
   // Emit new.
   builder.New(reg, reg, 0);
+  builder.New(wide, wide, 0);
 
   // Emit test operator invocations.
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::NE, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::EQ_STRICT, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::NE_STRICT, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::LT, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::GT, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::LTE, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::GTE, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::INSTANCEOF, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::IN, reg, Strength::WEAK);
+  builder.CompareOperation(Token::Value::EQ, reg)
+      .CompareOperation(Token::Value::NE, reg)
+      .CompareOperation(Token::Value::EQ_STRICT, reg)
+      .CompareOperation(Token::Value::NE_STRICT, reg)
+      .CompareOperation(Token::Value::LT, reg)
+      .CompareOperation(Token::Value::GT, reg)
+      .CompareOperation(Token::Value::LTE, reg)
+      .CompareOperation(Token::Value::GTE, reg)
+      .CompareOperation(Token::Value::INSTANCEOF, reg)
+      .CompareOperation(Token::Value::IN, reg);
 
   // Emit cast operator invocations.
   builder.CastAccumulatorToNumber()
@@ -168,50 +158,58 @@
   // Short jumps with Imm8 operands
   builder.Jump(&start)
       .JumpIfNull(&start)
-      .JumpIfUndefined(&start);
+      .JumpIfUndefined(&start)
+      .JumpIfNotHole(&start);
+
   // Perform an operation that returns boolean value to
   // generate JumpIfTrue/False
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+  builder.CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&start)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .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, Strength::WEAK)
+  builder.BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&start)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&start);
   // Insert dummy ops to force longer jumps
   for (int i = 0; i < 128; i++) {
     builder.LoadTrue();
   }
   // Longer jumps requiring Constant operand
-  builder.Jump(&start)
-      .JumpIfNull(&start)
-      .JumpIfUndefined(&start);
+  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, Strength::WEAK)
+  builder.CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&start)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .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, Strength::WEAK)
+  builder.BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&start)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&start);
 
-  // Emit 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);
+  // Emit stack check bytecode.
+  builder.StackCheck();
 
-  builder.ForInPrepare(reg, reg, reg)
+  // 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);
+  BytecodeLabel after_rethrow;
+  builder.Jump(&after_rethrow).ReThrow().Bind(&after_rethrow);
+
+  builder.ForInPrepare(reg)
       .ForInDone(reg, reg)
-      .ForInNext(reg, reg, reg, reg)
+      .ForInNext(reg, reg, reg)
+      .ForInStep(reg);
+  builder.ForInPrepare(wide)
+      .ForInDone(reg, other)
+      .ForInNext(wide, wide, wide)
       .ForInStep(reg);
 
   // Wide constant pool loads
@@ -223,28 +221,21 @@
   Handle<String> wide_name = factory->NewStringFromStaticChars("var_wide_name");
 
   // Emit wide global load / store operations.
-  builder.LoadGlobal(name, 1024, LanguageMode::SLOPPY,
-                     TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(wide_name, 1, LanguageMode::STRICT,
-                  TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(name, 1024, LanguageMode::SLOPPY, TypeofMode::INSIDE_TYPEOF)
-      .LoadGlobal(wide_name, 1, LanguageMode::STRICT, TypeofMode::INSIDE_TYPEOF)
+  builder.LoadGlobal(name, 1024, TypeofMode::NOT_INSIDE_TYPEOF)
+      .LoadGlobal(name, 1024, TypeofMode::INSIDE_TYPEOF)
       .StoreGlobal(name, 1024, LanguageMode::SLOPPY)
       .StoreGlobal(wide_name, 1, LanguageMode::STRICT);
 
   // Emit wide load / store property operations.
-  builder.LoadNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY)
-      .LoadKeyedProperty(reg, 2056, LanguageMode::SLOPPY)
+  builder.LoadNamedProperty(reg, wide_name, 0)
+      .LoadKeyedProperty(reg, 2056)
       .StoreNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY)
       .StoreKeyedProperty(reg, reg, 2056, LanguageMode::SLOPPY)
-      .LoadNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
-      .LoadKeyedProperty(reg, 2056, LanguageMode::STRICT)
       .StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
       .StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT);
 
   // Emit wide context operations.
-  builder.LoadContextSlot(reg, 1024)
-      .StoreContextSlot(reg, 1024);
+  builder.LoadContextSlot(reg, 1024).StoreContextSlot(reg, 1024);
 
   // Emit wide load / store lookup slots.
   builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF)
@@ -265,26 +256,31 @@
       .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0);
 
   // Longer jumps requiring ConstantWide operand
-  builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start);
+  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, Strength::WEAK)
+  builder.CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&start)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .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, Strength::WEAK)
+  builder.BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&start)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&start);
 
+  builder.Debugger();
+
   builder.Return();
 
   // Generate BytecodeArray.
   Handle<BytecodeArray> the_array = builder.ToBytecodeArray();
   CHECK_EQ(the_array->frame_size(),
-           builder.fixed_register_count() * kPointerSize);
+           (builder.fixed_and_temporary_register_count() +
+            builder.translation_register_count()) *
+               kPointerSize);
 
   // Build scorecard of bytecodes encountered in the BytecodeArray.
   std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1);
@@ -301,9 +297,11 @@
   CHECK_EQ(final_bytecode, Bytecode::kReturn);
   CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
 
-#define CHECK_BYTECODE_PRESENT(Name, ...)     \
-  /* Check Bytecode is marked in scorecard */ \
-  CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1);
+#define CHECK_BYTECODE_PRESENT(Name, ...)                                \
+  /* Check Bytecode is marked in scorecard, unless it's a debug break */ \
+  if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) {                     \
+    CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1);        \
+  }
   BYTECODE_LIST(CHECK_BYTECODE_PRESENT)
 #undef CHECK_BYTECODE_PRESENT
 }
@@ -313,12 +311,9 @@
   for (int locals = 0; locals < 5; locals++) {
     for (int contexts = 0; contexts < 4; contexts++) {
       for (int temps = 0; temps < 3; temps++) {
-        BytecodeArrayBuilder builder(isolate(), zone());
-        builder.set_parameter_count(0);
-        builder.set_locals_count(locals);
-        builder.set_context_count(contexts);
-
-        BytecodeRegisterAllocator temporaries(&builder);
+        BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals);
+        BytecodeRegisterAllocator temporaries(
+            zone(), builder.temporary_register_allocator());
         for (int i = 0; i < temps; i++) {
           builder.StoreAccumulatorInRegister(temporaries.NewRegister());
         }
@@ -349,11 +344,7 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, Parameters) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(10);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-
+  BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0);
   Register param0(builder.Parameter(0));
   Register param9(builder.Parameter(9));
   CHECK_EQ(param9.index() - param0.index(), 9);
@@ -361,12 +352,9 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, RegisterType) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(10);
-  builder.set_locals_count(3);
-  builder.set_context_count(0);
-
-  BytecodeRegisterAllocator register_allocator(&builder);
+  BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3);
+  BytecodeRegisterAllocator register_allocator(
+      zone(), builder.temporary_register_allocator());
   Register temp0 = register_allocator.NewRegister();
   Register param0(builder.Parameter(0));
   Register param9(builder.Parameter(9));
@@ -387,11 +375,7 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, Constants) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-
+  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);
@@ -402,7 +386,8 @@
       .LoadLiteral(large_smi)
       .LoadLiteral(heap_num_1)
       .LoadLiteral(heap_num_1)
-      .LoadLiteral(heap_num_2_copy);
+      .LoadLiteral(heap_num_2_copy)
+      .Return();
 
   Handle<BytecodeArray> array = builder.ToBytecodeArray();
   // Should only have one entry for each identical constant.
@@ -413,23 +398,19 @@
 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
   static const int kFarJumpDistance = 256;
 
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(1);
-  builder.set_context_count(0);
-
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
   Register reg(0);
   BytecodeLabel far0, far1, far2, far3, far4;
   BytecodeLabel near0, near1, near2, near3, near4;
 
   builder.Jump(&near0)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&near1)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&near2)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&near3)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&near4)
       .Bind(&near0)
       .Bind(&near1)
@@ -437,13 +418,13 @@
       .Bind(&near3)
       .Bind(&near4)
       .Jump(&far0)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&far1)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&far2)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&far3)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&far4);
   for (int i = 0; i < kFarJumpDistance - 18; i++) {
     builder.LoadUndefined();
@@ -529,38 +510,31 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(1);
-  builder.set_context_count(0);
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
   Register reg(0);
 
   BytecodeLabel label0, label1, label2, label3, label4;
   builder.Bind(&label0)
       .Jump(&label0)
       .Bind(&label1)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&label1)
       .Bind(&label2)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&label2)
       .Bind(&label3)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&label3)
       .Bind(&label4)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&label4);
   for (int i = 0; i < 63; i++) {
     builder.Jump(&label4);
   }
-  builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
-      .JumpIfFalse(&label4);
-  builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
-      .JumpIfTrue(&label3);
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
-      .JumpIfFalse(&label2);
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
-      .JumpIfTrue(&label1);
+  builder.BinaryOperation(Token::Value::ADD, reg).JumpIfFalse(&label4);
+  builder.BinaryOperation(Token::Value::ADD, reg).JumpIfTrue(&label3);
+  builder.CompareOperation(Token::Value::EQ, reg).JumpIfFalse(&label2);
+  builder.CompareOperation(Token::Value::EQ, reg).JumpIfTrue(&label1);
   builder.Jump(&label0);
   builder.Return();
 
@@ -625,10 +599,7 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
 
   // Labels can only have 1 forward reference, but
   // can be referred to mulitple times once bound.
@@ -656,16 +627,11 @@
 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
   static const int kRepeats = 3;
 
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-
+  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);
   }
-
   builder.Return();
 
   Handle<BytecodeArray> array = builder.ToBytecodeArray();
@@ -686,7 +652,6 @@
   CHECK(iterator.done());
 }
 
-
 }  // 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 cd9f120..f2dcd71 100644
--- a/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
+++ b/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
@@ -22,11 +22,7 @@
 TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
   // Use a builder to create an array with containing multiple bytecodes
   // with 0, 1 and 2 operands.
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(3);
-  builder.set_locals_count(2);
-  builder.set_context_count(0);
-
+  BytecodeArrayBuilder builder(isolate(), zone(), 3, 2, 0);
   Factory* factory = isolate()->factory();
   Handle<HeapObject> heap_num_0 = factory->NewHeapNumber(2.718);
   Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(2147483647);
@@ -46,9 +42,10 @@
       .LoadLiteral(smi_0)
       .LoadLiteral(smi_1)
       .LoadAccumulatorWithRegister(reg_0)
-      .LoadNamedProperty(reg_1, name, feedback_slot, LanguageMode::SLOPPY)
+      .LoadNamedProperty(reg_1, name, feedback_slot)
       .StoreAccumulatorInRegister(reg_2)
       .CallRuntime(Runtime::kLoadIC_Miss, reg_0, 1)
+      .Debugger()
       .Return();
 
   // Test iterator sees the expected output from the builder.
@@ -82,7 +79,7 @@
   CHECK(!iterator.done());
   iterator.Advance();
 
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadICSloppy);
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadIC);
   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
   CHECK_EQ(iterator.GetIndexOperand(1), name_index);
   CHECK_EQ(iterator.GetIndexOperand(2), feedback_slot);
@@ -98,7 +95,11 @@
   CHECK_EQ(static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0)),
            Runtime::kLoadIC_Miss);
   CHECK_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
-  CHECK_EQ(iterator.GetCountOperand(2), 1);
+  CHECK_EQ(iterator.GetRegisterCountOperand(2), 1);
+  CHECK(!iterator.done());
+  iterator.Advance();
+
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
   CHECK(!iterator.done());
   iterator.Advance();
 
diff --git a/test/unittests/interpreter/bytecode-register-allocator-unittest.cc b/test/unittests/interpreter/bytecode-register-allocator-unittest.cc
index 0620322..ec29935 100644
--- a/test/unittests/interpreter/bytecode-register-allocator-unittest.cc
+++ b/test/unittests/interpreter/bytecode-register-allocator-unittest.cc
@@ -12,51 +12,219 @@
 namespace internal {
 namespace interpreter {
 
+class TemporaryRegisterAllocatorTest : public TestWithIsolateAndZone {
+ public:
+  TemporaryRegisterAllocatorTest() : allocator_(zone(), 0) {}
+  ~TemporaryRegisterAllocatorTest() override {}
+  TemporaryRegisterAllocator* allocator() { return &allocator_; }
+
+ private:
+  TemporaryRegisterAllocator allocator_;
+};
+
+TEST_F(TemporaryRegisterAllocatorTest, FirstAllocation) {
+  CHECK_EQ(allocator()->allocation_count(), 0);
+  int reg0_index = allocator()->BorrowTemporaryRegister();
+  CHECK_EQ(reg0_index, 0);
+  CHECK_EQ(allocator()->allocation_count(), 1);
+  CHECK(allocator()->RegisterIsLive(Register(reg0_index)));
+  allocator()->ReturnTemporaryRegister(reg0_index);
+  CHECK(!allocator()->RegisterIsLive(Register(reg0_index)));
+  CHECK_EQ(allocator()->allocation_count(), 1);
+  CHECK(allocator()->first_temporary_register() == Register(0));
+  CHECK(allocator()->last_temporary_register() == Register(0));
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, SimpleAllocations) {
+  for (int i = 0; i < 13; i++) {
+    int reg_index = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(reg_index, i);
+    CHECK_EQ(allocator()->allocation_count(), i + 1);
+  }
+  for (int i = 0; i < 13; i++) {
+    CHECK(allocator()->RegisterIsLive(Register(i)));
+    allocator()->ReturnTemporaryRegister(i);
+    CHECK(!allocator()->RegisterIsLive(Register(i)));
+    int reg_index = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(reg_index, i);
+    CHECK_EQ(allocator()->allocation_count(), 13);
+  }
+  for (int i = 0; i < 13; i++) {
+    CHECK(allocator()->RegisterIsLive(Register(i)));
+    allocator()->ReturnTemporaryRegister(i);
+    CHECK(!allocator()->RegisterIsLive(Register(i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, SimpleRangeAllocation) {
+  static const int kRunLength = 7;
+  int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+  CHECK(!allocator()->RegisterIsLive(Register(start)));
+  for (int i = 0; i < kRunLength; i++) {
+    CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+    allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+    CHECK(allocator()->RegisterIsLive(Register(start + i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingFree) {
+  static const int kFreeCount = 3;
+  static const int kRunLength = 6;
+
+  for (int i = 0; i < kFreeCount; i++) {
+    int to_free = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(to_free, i);
+  }
+  for (int i = 0; i < kFreeCount; i++) {
+    allocator()->ReturnTemporaryRegister(i);
+  }
+
+  int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+  CHECK(!allocator()->RegisterIsLive(Register(start)));
+  for (int i = 0; i < kRunLength; i++) {
+    CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+    allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+    CHECK(allocator()->RegisterIsLive(Register(start + i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingHole) {
+  static const int kPreAllocatedCount = 7;
+  static const int kPreAllocatedFreeCount = 6;
+  static const int kRunLength = 8;
+
+  for (int i = 0; i < kPreAllocatedCount; i++) {
+    int to_free = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(to_free, i);
+  }
+  for (int i = 0; i < kPreAllocatedFreeCount; i++) {
+    allocator()->ReturnTemporaryRegister(i);
+  }
+  int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+  CHECK(!allocator()->RegisterIsLive(Register(start)));
+  CHECK_EQ(start, kPreAllocatedCount);
+  for (int i = 0; i < kRunLength; i++) {
+    CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+    allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+    CHECK(allocator()->RegisterIsLive(Register(start + i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAvailableInTemporaries) {
+  static const int kNotRunLength = 13;
+  static const int kRunLength = 8;
+
+  // Allocate big batch
+  for (int i = 0; i < kNotRunLength * 2 + kRunLength; i++) {
+    int allocated = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(allocated, i);
+  }
+  // Free every other register either side of target.
+  for (int i = 0; i < kNotRunLength; i++) {
+    if ((i & 2) == 1) {
+      allocator()->ReturnTemporaryRegister(i);
+      allocator()->ReturnTemporaryRegister(kNotRunLength + kRunLength + i);
+    }
+  }
+  // Free all registers for target.
+  for (int i = kNotRunLength; i < kNotRunLength + kRunLength; i++) {
+    allocator()->ReturnTemporaryRegister(i);
+  }
+
+  int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+  CHECK_EQ(start, kNotRunLength);
+  for (int i = 0; i < kRunLength; i++) {
+    CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+    allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+    CHECK(allocator()->RegisterIsLive(Register(start + i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAvoidsTranslationBoundary) {
+  int boundary = RegisterTranslator::DistanceToTranslationWindow(Register(0));
+  int limit = boundary + 64;
+
+  for (int run_length = 2; run_length < 32; run_length += 7) {
+    ZoneVector<int> run_starts(zone());
+    for (int start = 0; start < limit; start += run_length) {
+      int run_start =
+          allocator()->PrepareForConsecutiveTemporaryRegisters(run_length);
+      run_starts.push_back(run_start);
+      for (int i = 0; i < run_length; i++) {
+        allocator()->BorrowConsecutiveTemporaryRegister(run_start + i);
+      }
+      CHECK(run_start >= boundary || run_start + run_length <= boundary);
+    }
+    for (size_t batch = 0; batch < run_starts.size(); batch++) {
+      for (int i = run_starts[batch]; i < run_starts[batch] + run_length; i++) {
+        allocator()->ReturnTemporaryRegister(i);
+      }
+    }
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, NotInRange) {
+  for (int i = 0; i < 10; i++) {
+    int reg = allocator()->BorrowTemporaryRegisterNotInRange(2, 5);
+    CHECK(reg == i || (reg > 2 && reg == i + 4));
+  }
+  for (int i = 0; i < 10; i++) {
+    if (i < 2) {
+      allocator()->ReturnTemporaryRegister(i);
+    } else {
+      allocator()->ReturnTemporaryRegister(i + 4);
+    }
+  }
+  int reg0 = allocator()->BorrowTemporaryRegisterNotInRange(0, 3);
+  CHECK_EQ(reg0, 4);
+  int reg1 = allocator()->BorrowTemporaryRegisterNotInRange(3, 10);
+  CHECK_EQ(reg1, 2);
+  int reg2 = allocator()->BorrowTemporaryRegisterNotInRange(2, 6);
+  CHECK_EQ(reg2, 1);
+  allocator()->ReturnTemporaryRegister(reg0);
+  allocator()->ReturnTemporaryRegister(reg1);
+  allocator()->ReturnTemporaryRegister(reg2);
+}
+
 class BytecodeRegisterAllocatorTest : public TestWithIsolateAndZone {
  public:
   BytecodeRegisterAllocatorTest() {}
   ~BytecodeRegisterAllocatorTest() override {}
 };
 
-
 TEST_F(BytecodeRegisterAllocatorTest, TemporariesRecycled) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
 
   int first;
   {
-    BytecodeRegisterAllocator temporaries(&builder);
-    first = temporaries.NewRegister().index();
-    temporaries.NewRegister();
-    temporaries.NewRegister();
-    temporaries.NewRegister();
+    BytecodeRegisterAllocator allocator(zone(),
+                                        builder.temporary_register_allocator());
+    first = allocator.NewRegister().index();
+    allocator.NewRegister();
+    allocator.NewRegister();
+    allocator.NewRegister();
   }
 
   int second;
   {
-    BytecodeRegisterAllocator temporaries(&builder);
-    second = temporaries.NewRegister().index();
+    BytecodeRegisterAllocator allocator(zone(),
+                                        builder.temporary_register_allocator());
+    second = allocator.NewRegister().index();
   }
 
   CHECK_EQ(first, second);
 }
 
-
 TEST_F(BytecodeRegisterAllocatorTest, ConsecutiveRegisters) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-
-  BytecodeRegisterAllocator temporaries(&builder);
-  temporaries.PrepareForConsecutiveAllocations(4);
-  Register reg0 = temporaries.NextConsecutiveRegister();
-  Register other = temporaries.NewRegister();
-  Register reg1 = temporaries.NextConsecutiveRegister();
-  Register reg2 = temporaries.NextConsecutiveRegister();
-  Register reg3 = temporaries.NextConsecutiveRegister();
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
+  BytecodeRegisterAllocator allocator(zone(),
+                                      builder.temporary_register_allocator());
+  allocator.PrepareForConsecutiveAllocations(4);
+  Register reg0 = allocator.NextConsecutiveRegister();
+  Register other = allocator.NewRegister();
+  Register reg1 = allocator.NextConsecutiveRegister();
+  Register reg2 = allocator.NextConsecutiveRegister();
+  Register reg3 = allocator.NextConsecutiveRegister();
   USE(other);
 
   CHECK(Register::AreContiguous(reg0, reg1, reg2, reg3));
diff --git a/test/unittests/interpreter/bytecodes-unittest.cc b/test/unittests/interpreter/bytecodes-unittest.cc
index 812ee46..212e029 100644
--- a/test/unittests/interpreter/bytecodes-unittest.cc
+++ b/test/unittests/interpreter/bytecodes-unittest.cc
@@ -9,20 +9,40 @@
 #include "src/interpreter/bytecodes.h"
 #include "test/unittests/test-utils.h"
 
-
 namespace v8 {
 namespace internal {
 namespace interpreter {
 
 TEST(OperandConversion, Registers) {
-  for (int i = 0; i < 128; i++) {
-    uint8_t operand_value = Register(i).ToOperand();
-    Register r = Register::FromOperand(operand_value);
-    CHECK_EQ(i, r.index());
+  int register_count = Register::MaxRegisterIndex() + 1;
+  int step = register_count / 7;
+  for (int i = 0; i < register_count; i += step) {
+    if (i <= kMaxInt8) {
+      uint8_t operand0 = Register(i).ToOperand();
+      Register reg0 = Register::FromOperand(operand0);
+      CHECK_EQ(i, reg0.index());
+    }
+
+    uint16_t operand1 = Register(i).ToWideOperand();
+    Register reg1 = Register::FromWideOperand(operand1);
+    CHECK_EQ(i, reg1.index());
+
+    uint32_t operand2 = Register(i).ToRawOperand();
+    Register reg2 = Register::FromRawOperand(operand2);
+    CHECK_EQ(i, reg2.index());
+  }
+
+  for (int i = 0; i <= kMaxUInt8; i++) {
+    uint8_t operand = static_cast<uint8_t>(i);
+    Register reg = Register::FromOperand(operand);
+    if (i > 0 && i < -kMinInt8) {
+      CHECK(reg.is_parameter());
+    } else {
+      CHECK(!reg.is_parameter());
+    }
   }
 }
 
-
 TEST(OperandConversion, Parameters) {
   int parameter_counts[] = {7, 13, 99};
 
@@ -38,26 +58,115 @@
   }
 }
 
-
 TEST(OperandConversion, RegistersParametersNoOverlap) {
-  std::vector<uint8_t> operand_count(256);
+  int register_count = Register::MaxRegisterIndex() + 1;
+  int parameter_count = Register::MaxParameterIndex() + 1;
+  int32_t register_space_size = base::bits::RoundUpToPowerOfTwo32(
+      static_cast<uint32_t>(register_count + parameter_count));
+  uint32_t range = static_cast<uint32_t>(register_space_size);
+  std::vector<uint8_t> operand_count(range);
 
-  for (int i = 0; i <= kMaxInt8; i++) {
+  for (int i = 0; i < register_count; i += 1) {
     Register r = Register(i);
-    uint8_t operand = r.ToOperand();
+    uint32_t operand = r.ToWideOperand();
+    CHECK_LT(operand, operand_count.size());
     operand_count[operand] += 1;
     CHECK_EQ(operand_count[operand], 1);
   }
 
-  int parameter_count = Register::MaxParameterIndex() + 1;
-  for (int i = 0; i < parameter_count; i++) {
+  for (int i = 0; i < parameter_count; i += 1) {
     Register r = Register::FromParameterIndex(i, parameter_count);
-    uint8_t operand = r.ToOperand();
+    uint32_t operand = r.ToWideOperand();
+    CHECK_LT(operand, operand_count.size());
     operand_count[operand] += 1;
     CHECK_EQ(operand_count[operand], 1);
   }
 }
 
+TEST(Bytecodes, HasAnyRegisterOperands) {
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kAdd), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCall), 2);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntime), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntimeWide), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntimeForPair),
+           2);
+  CHECK_EQ(
+      Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntimeForPairWide),
+      2);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kDeletePropertyStrict),
+           1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kForInPrepare), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kForInPrepareWide), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kInc), 0);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kJumpIfTrue), 0);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kNew), 2);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kToName), 0);
+}
+
+TEST(Bytecodes, RegisterOperandBitmaps) {
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kAdd), 1);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kCallRuntimeForPair),
+           10);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kStar), 1);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kMov), 3);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kTestIn), 1);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kForInPrepare), 1);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kForInDone), 3);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kForInNext), 7);
+}
+
+TEST(Bytecodes, RegisterOperands) {
+  CHECK(Bytecodes::IsRegisterOperandType(OperandType::kReg8));
+  CHECK(Bytecodes::IsRegisterInputOperandType(OperandType::kReg8));
+  CHECK(!Bytecodes::IsRegisterOutputOperandType(OperandType::kReg8));
+  CHECK(!Bytecodes::IsRegisterInputOperandType(OperandType::kRegOut8));
+  CHECK(Bytecodes::IsRegisterOutputOperandType(OperandType::kRegOut8));
+
+#define IS_REGISTER_OPERAND_TYPE(Name, _) \
+  CHECK(Bytecodes::IsRegisterOperandType(OperandType::k##Name));
+  REGISTER_OPERAND_TYPE_LIST(IS_REGISTER_OPERAND_TYPE)
+#undef IS_REGISTER_OPERAND_TYPE
+
+#define IS_NOT_REGISTER_OPERAND_TYPE(Name, _) \
+  CHECK(!Bytecodes::IsRegisterOperandType(OperandType::k##Name));
+  NON_REGISTER_OPERAND_TYPE_LIST(IS_NOT_REGISTER_OPERAND_TYPE)
+#undef IS_NOT_REGISTER_OPERAND_TYPE
+
+#define IS_REGISTER_INPUT_OPERAND_TYPE(Name, _) \
+  CHECK(Bytecodes::IsRegisterInputOperandType(OperandType::k##Name));
+  REGISTER_INPUT_OPERAND_TYPE_LIST(IS_REGISTER_INPUT_OPERAND_TYPE)
+#undef IS_REGISTER_INPUT_OPERAND_TYPE
+
+#define IS_NOT_REGISTER_INPUT_OPERAND_TYPE(Name, _) \
+  CHECK(!Bytecodes::IsRegisterInputOperandType(OperandType::k##Name));
+  NON_REGISTER_OPERAND_TYPE_LIST(IS_NOT_REGISTER_INPUT_OPERAND_TYPE);
+  REGISTER_OUTPUT_OPERAND_TYPE_LIST(IS_NOT_REGISTER_INPUT_OPERAND_TYPE)
+#undef IS_NOT_REGISTER_INPUT_OPERAND_TYPE
+
+#define IS_REGISTER_OUTPUT_OPERAND_TYPE(Name, _) \
+  CHECK(Bytecodes::IsRegisterOutputOperandType(OperandType::k##Name));
+  REGISTER_OUTPUT_OPERAND_TYPE_LIST(IS_REGISTER_OUTPUT_OPERAND_TYPE)
+#undef IS_REGISTER_OUTPUT_OPERAND_TYPE
+
+#define IS_NOT_REGISTER_OUTPUT_OPERAND_TYPE(Name, _) \
+  CHECK(!Bytecodes::IsRegisterOutputOperandType(OperandType::k##Name));
+  NON_REGISTER_OPERAND_TYPE_LIST(IS_NOT_REGISTER_OUTPUT_OPERAND_TYPE)
+  REGISTER_INPUT_OPERAND_TYPE_LIST(IS_NOT_REGISTER_OUTPUT_OPERAND_TYPE)
+#undef IS_NOT_REGISTER_INPUT_OPERAND_TYPE
+}
+
+TEST(Bytecodes, DebugBreak) {
+  for (uint32_t i = 0; i < Bytecodes::ToByte(Bytecode::kLast); i++) {
+    Bytecode bytecode = Bytecodes::FromByte(i);
+    Bytecode debugbreak = Bytecodes::GetDebugBreak(bytecode);
+    if (!Bytecodes::IsDebugBreak(debugbreak)) {
+      PrintF("Bytecode %s has no matching debug break with length %d\n",
+             Bytecodes::ToString(bytecode), Bytecodes::Size(bytecode));
+      CHECK(false);
+    }
+  }
+}
+
 }  // 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 ea5d1bb..b3ec5ff 100644
--- a/test/unittests/interpreter/constant-array-builder-unittest.cc
+++ b/test/unittests/interpreter/constant-array-builder-unittest.cc
@@ -33,13 +33,11 @@
 TEST_F(ConstantArrayBuilderTest, AllocateAllEntries) {
   ConstantArrayBuilder builder(isolate(), zone());
   for (size_t i = 0; i < kMaxCapacity; i++) {
-    Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
-    builder.Insert(object);
-    CHECK_EQ(builder.size(), i + 1);
-    CHECK(builder.At(i)->SameValue(*object));
+    builder.Insert(handle(Smi::FromInt(static_cast<int>(i)), isolate()));
   }
+  CHECK_EQ(builder.size(), kMaxCapacity);
   for (size_t i = 0; i < kMaxCapacity; i++) {
-    CHECK_EQ(Handle<Smi>::cast(builder.At(i))->value(), static_cast<double>(i));
+    CHECK_EQ(Handle<Smi>::cast(builder.At(i))->value(), i);
   }
 }
 
@@ -158,8 +156,7 @@
     builder.Insert(object);
     CHECK(builder.At(i)->SameValue(*object));
   }
-  Handle<FixedArray> constant_array =
-      builder.ToFixedArray(isolate()->factory());
+  Handle<FixedArray> constant_array = builder.ToFixedArray();
   CHECK_EQ(constant_array->length(), kNumberOfElements);
   for (size_t i = 0; i < kNumberOfElements; i++) {
     CHECK(constant_array->get(static_cast<int>(i))->SameValue(*builder.At(i)));
diff --git a/test/unittests/compiler/interpreter-assembler-unittest.cc b/test/unittests/interpreter/interpreter-assembler-unittest.cc
similarity index 65%
rename from test/unittests/compiler/interpreter-assembler-unittest.cc
rename to test/unittests/interpreter/interpreter-assembler-unittest.cc
index f57ca05..3375a6b 100644
--- a/test/unittests/compiler/interpreter-assembler-unittest.cc
+++ b/test/unittests/interpreter/interpreter-assembler-unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "test/unittests/compiler/interpreter-assembler-unittest.h"
+#include "test/unittests/interpreter/interpreter-assembler-unittest.h"
 
 #include "src/code-factory.h"
 #include "src/compiler/graph.h"
@@ -16,7 +16,10 @@
 
 namespace v8 {
 namespace internal {
-namespace compiler {
+
+using namespace compiler;
+
+namespace interpreter {
 
 const interpreter::Bytecode kBytecodes[] = {
 #define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
@@ -24,55 +27,47 @@
 #undef DEFINE_BYTECODE
 };
 
-
 Matcher<Node*> IsIntPtrConstant(const intptr_t value) {
   return kPointerSize == 8 ? IsInt64Constant(static_cast<int64_t>(value))
                            : IsInt32Constant(static_cast<int32_t>(value));
 }
 
-
 Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher,
                            const Matcher<Node*>& rhs_matcher) {
   return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher)
                            : IsInt32Add(lhs_matcher, rhs_matcher);
 }
 
-
 Matcher<Node*> IsIntPtrSub(const Matcher<Node*>& lhs_matcher,
                            const Matcher<Node*>& rhs_matcher) {
   return kPointerSize == 8 ? IsInt64Sub(lhs_matcher, rhs_matcher)
                            : IsInt32Sub(lhs_matcher, rhs_matcher);
 }
 
-
 Matcher<Node*> IsWordShl(const Matcher<Node*>& lhs_matcher,
                          const Matcher<Node*>& rhs_matcher) {
   return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher)
                            : IsWord32Shl(lhs_matcher, rhs_matcher);
 }
 
-
 Matcher<Node*> IsWordSar(const Matcher<Node*>& lhs_matcher,
                          const Matcher<Node*>& rhs_matcher) {
   return kPointerSize == 8 ? IsWord64Sar(lhs_matcher, rhs_matcher)
                            : IsWord32Sar(lhs_matcher, rhs_matcher);
 }
 
-
 Matcher<Node*> IsWordOr(const Matcher<Node*>& lhs_matcher,
                         const Matcher<Node*>& rhs_matcher) {
   return kPointerSize == 8 ? IsWord64Or(lhs_matcher, rhs_matcher)
                            : IsWord32Or(lhs_matcher, rhs_matcher);
 }
 
-
 Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoad(
     const Matcher<LoadRepresentation>& rep_matcher,
     const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher) {
   return ::i::compiler::IsLoad(rep_matcher, base_matcher, index_matcher, _, _);
 }
 
-
 Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
     const Matcher<StoreRepresentation>& rep_matcher,
     const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
@@ -81,52 +76,57 @@
                                 value_matcher, _, _);
 }
 
-
 Matcher<Node*>
 InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperand(
     int offset) {
   return IsLoad(
       MachineType::Uint8(),
-      IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-      IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                  IsInt32Constant(offset)));
+      IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+      IsIntPtrAdd(
+          IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+          IsInt32Constant(offset)));
 }
 
-
 Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
     IsBytecodeOperandSignExtended(int offset) {
   Matcher<Node*> load_matcher = IsLoad(
       MachineType::Int8(),
-      IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-      IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                  IsInt32Constant(offset)));
+      IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+      IsIntPtrAdd(
+          IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+          IsInt32Constant(offset)));
   if (kPointerSize == 8) {
     load_matcher = IsChangeInt32ToInt64(load_matcher);
   }
   return load_matcher;
 }
 
-
 Matcher<Node*>
 InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperandShort(
     int offset) {
   if (TargetSupportsUnalignedAccess()) {
     return IsLoad(
         MachineType::Uint16(),
-        IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-        IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                    IsInt32Constant(offset)));
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(offset)));
   } else {
     Matcher<Node*> first_byte = IsLoad(
         MachineType::Uint8(),
-        IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-        IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                    IsInt32Constant(offset)));
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(offset)));
     Matcher<Node*> second_byte = IsLoad(
         MachineType::Uint8(),
-        IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-        IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                    IsInt32Constant(offset + 1)));
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(offset + 1)));
 #if V8_TARGET_LITTLE_ENDIAN
     return IsWordOr(IsWordShl(second_byte, IsInt32Constant(kBitsPerByte)),
                     first_byte);
@@ -139,16 +139,17 @@
   }
 }
 
-
 Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
     IsBytecodeOperandShortSignExtended(int offset) {
   Matcher<Node*> load_matcher;
   if (TargetSupportsUnalignedAccess()) {
     load_matcher = IsLoad(
         MachineType::Int16(),
-        IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-        IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                    IsInt32Constant(offset)));
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(offset)));
   } else {
 #if V8_TARGET_LITTLE_ENDIAN
     int hi_byte_offset = offset + 1;
@@ -162,15 +163,19 @@
 #endif
     Matcher<Node*> hi_byte = IsLoad(
         MachineType::Int8(),
-        IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-        IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                    IsInt32Constant(hi_byte_offset)));
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(hi_byte_offset)));
     hi_byte = IsWord32Shl(hi_byte, IsInt32Constant(kBitsPerByte));
     Matcher<Node*> lo_byte = IsLoad(
         MachineType::Uint8(),
-        IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-        IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                    IsInt32Constant(lo_byte_offset)));
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(lo_byte_offset)));
     load_matcher = IsWord32Or(hi_byte, lo_byte);
   }
 
@@ -180,7 +185,6 @@
   return load_matcher;
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -191,35 +195,37 @@
     EXPECT_EQ(1, end->InputCount());
     Node* tail_call_node = end->InputAt(0);
 
-    Matcher<Node*> next_bytecode_offset_matcher =
-        IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                    IsInt32Constant(interpreter::Bytecodes::Size(bytecode)));
-    Matcher<Node*> target_bytecode_matcher =
-        m.IsLoad(MachineType::Uint8(),
-                 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-                 next_bytecode_offset_matcher);
-    Matcher<Node*> code_target_matcher =
-        m.IsLoad(MachineType::Pointer(),
-                 IsParameter(Linkage::kInterpreterDispatchTableParameter),
-                 IsWord32Shl(target_bytecode_matcher,
-                             IsInt32Constant(kPointerSizeLog2)));
+    Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+        IsInt32Constant(interpreter::Bytecodes::Size(bytecode)));
+    Matcher<Node*> target_bytecode_matcher = m.IsLoad(
+        MachineType::Uint8(),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        next_bytecode_offset_matcher);
+    Matcher<Node*> code_target_matcher = m.IsLoad(
+        MachineType::Pointer(),
+        IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+        IsWord32Shl(target_bytecode_matcher,
+                    IsInt32Constant(kPointerSizeLog2)));
 
-    EXPECT_EQ(CallDescriptor::kCallCodeObject, m.call_descriptor()->kind());
-    EXPECT_TRUE(m.call_descriptor()->flags() & CallDescriptor::kCanUseRoots);
     EXPECT_THAT(
         tail_call_node,
-        IsTailCall(m.call_descriptor(), code_target_matcher,
-                   IsParameter(Linkage::kInterpreterAccumulatorParameter),
-                   IsParameter(Linkage::kInterpreterRegisterFileParameter),
-                   next_bytecode_offset_matcher,
-                   IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-                   IsParameter(Linkage::kInterpreterDispatchTableParameter),
-                   IsParameter(Linkage::kInterpreterContextParameter), _, _));
+        IsTailCall(
+            _, code_target_matcher,
+            IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+            next_bytecode_offset_matcher,
+            IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+            IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+            IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+            _));
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
+  // If debug code is enabled we emit extra code in Jump.
+  if (FLAG_debug_code) return;
+
   int jump_offsets[] = {-9710, -77, 0, +3, +97109};
   TRACED_FOREACH(int, jump_offset, jump_offsets) {
     TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
@@ -230,38 +236,39 @@
       EXPECT_EQ(1, end->InputCount());
       Node* tail_call_node = end->InputAt(0);
 
-      Matcher<Node*> next_bytecode_offset_matcher =
-          IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                      IsInt32Constant(jump_offset));
+      Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
+          IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+          IsInt32Constant(jump_offset));
       Matcher<Node*> target_bytecode_matcher =
-          m.IsLoad(MachineType::Uint8(),
-                   IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-                   next_bytecode_offset_matcher);
-      Matcher<Node*> code_target_matcher =
-          m.IsLoad(MachineType::Pointer(),
-                   IsParameter(Linkage::kInterpreterDispatchTableParameter),
-                   IsWord32Shl(target_bytecode_matcher,
-                               IsInt32Constant(kPointerSizeLog2)));
+          m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
+      Matcher<Node*> code_target_matcher = m.IsLoad(
+          MachineType::Pointer(),
+          IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+          IsWord32Shl(target_bytecode_matcher,
+                      IsInt32Constant(kPointerSizeLog2)));
 
-      EXPECT_EQ(CallDescriptor::kCallCodeObject, m.call_descriptor()->kind());
-      EXPECT_TRUE(m.call_descriptor()->flags() & CallDescriptor::kCanUseRoots);
       EXPECT_THAT(
           tail_call_node,
-          IsTailCall(m.call_descriptor(), code_target_matcher,
-                     IsParameter(Linkage::kInterpreterAccumulatorParameter),
-                     IsParameter(Linkage::kInterpreterRegisterFileParameter),
-                     next_bytecode_offset_matcher,
-                     IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-                     IsParameter(Linkage::kInterpreterDispatchTableParameter),
-                     IsParameter(Linkage::kInterpreterContextParameter), _, _));
+          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) {
@@ -276,61 +283,64 @@
     int jump_offsets[] = {kJumpIfTrueOffset,
                           interpreter::Bytecodes::Size(bytecode)};
     for (int i = 0; i < static_cast<int>(arraysize(jump_offsets)); i++) {
-      Matcher<Node*> next_bytecode_offset_matcher =
-          IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                      IsInt32Constant(jump_offsets[i]));
+      Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
+          IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+          IsInt32Constant(jump_offsets[i]));
       Matcher<Node*> target_bytecode_matcher =
-          m.IsLoad(MachineType::Uint8(),
-                   IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-                   next_bytecode_offset_matcher);
-      Matcher<Node*> code_target_matcher =
-          m.IsLoad(MachineType::Pointer(),
-                   IsParameter(Linkage::kInterpreterDispatchTableParameter),
-                   IsWord32Shl(target_bytecode_matcher,
-                               IsInt32Constant(kPointerSizeLog2)));
+          m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
+      Matcher<Node*> code_target_matcher = m.IsLoad(
+          MachineType::Pointer(),
+          IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+          IsWord32Shl(target_bytecode_matcher,
+                      IsInt32Constant(kPointerSizeLog2)));
       EXPECT_THAT(
           end->InputAt(i),
-          IsTailCall(m.call_descriptor(), code_target_matcher,
-                     IsParameter(Linkage::kInterpreterAccumulatorParameter),
-                     IsParameter(Linkage::kInterpreterRegisterFileParameter),
-                     next_bytecode_offset_matcher,
-                     IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-                     IsParameter(Linkage::kInterpreterDispatchTableParameter),
-                     IsParameter(Linkage::kInterpreterContextParameter), _, _));
+          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;
 
-TARGET_TEST_F(InterpreterAssemblerTest, Return) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
-    m.Return();
+    m.InterpreterReturn();
     Graph* graph = m.graph();
 
     Node* end = graph->end();
     EXPECT_EQ(1, end->InputCount());
     Node* tail_call_node = end->InputAt(0);
 
-    EXPECT_EQ(CallDescriptor::kCallCodeObject, m.call_descriptor()->kind());
-    EXPECT_TRUE(m.call_descriptor()->flags() & CallDescriptor::kCanUseRoots);
     Handle<HeapObject> exit_trampoline =
         isolate()->builtins()->InterpreterExitTrampoline();
     EXPECT_THAT(
         tail_call_node,
-        IsTailCall(m.call_descriptor(), IsHeapConstant(exit_trampoline),
-                   IsParameter(Linkage::kInterpreterAccumulatorParameter),
-                   IsParameter(Linkage::kInterpreterRegisterFileParameter),
-                   IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
-                   IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
-                   IsParameter(Linkage::kInterpreterDispatchTableParameter),
-                   IsParameter(Linkage::kInterpreterContextParameter), _, _));
+        IsTailCall(
+            _, IsHeapConstant(exit_trampoline),
+            IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            _,
+            IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+            IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+            _));
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -338,7 +348,7 @@
     for (int i = 0; i < number_of_operands; i++) {
       int offset = interpreter::Bytecodes::GetOperandOffset(bytecode, i);
       switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
-        case interpreter::OperandType::kCount8:
+        case interpreter::OperandType::kRegCount8:
           EXPECT_THAT(m.BytecodeOperandCount(i), m.IsBytecodeOperand(offset));
           break;
         case interpreter::OperandType::kIdx8:
@@ -350,11 +360,14 @@
           break;
         case interpreter::OperandType::kMaybeReg8:
         case interpreter::OperandType::kReg8:
+        case interpreter::OperandType::kRegOut8:
+        case interpreter::OperandType::kRegOutPair8:
+        case interpreter::OperandType::kRegOutTriple8:
         case interpreter::OperandType::kRegPair8:
           EXPECT_THAT(m.BytecodeOperandReg(i),
                       m.IsBytecodeOperandSignExtended(offset));
           break;
-        case interpreter::OperandType::kCount16:
+        case interpreter::OperandType::kRegCount16:
           EXPECT_THAT(m.BytecodeOperandCount(i),
                       m.IsBytecodeOperandShort(offset));
           break;
@@ -362,7 +375,12 @@
           EXPECT_THAT(m.BytecodeOperandIdx(i),
                       m.IsBytecodeOperandShort(offset));
           break;
+        case interpreter::OperandType::kMaybeReg16:
         case interpreter::OperandType::kReg16:
+        case interpreter::OperandType::kRegOut16:
+        case interpreter::OperandType::kRegOutPair16:
+        case interpreter::OperandType::kRegOutTriple16:
+        case interpreter::OperandType::kRegPair16:
           EXPECT_THAT(m.BytecodeOperandReg(i),
                       m.IsBytecodeOperandShortSignExtended(offset));
           break;
@@ -374,15 +392,15 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
     // Should be incoming accumulator if not set.
-    EXPECT_THAT(m.GetAccumulator(),
-                IsParameter(Linkage::kInterpreterAccumulatorParameter));
+    EXPECT_THAT(
+        m.GetAccumulator(),
+        IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter));
 
-    // Should be set by SedtAccumulator.
+    // Should be set by SetAccumulator.
     Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef);
     m.SetAccumulator(accumulator_value_1);
     EXPECT_THAT(m.GetAccumulator(), accumulator_value_1);
@@ -399,11 +417,18 @@
     Node* tail_call_node = end->InputAt(0);
 
     EXPECT_THAT(tail_call_node,
-                IsTailCall(m.call_descriptor(), _, accumulator_value_2, _, _, _,
-                           _, _, _));
+                IsTailCall(_, _, accumulator_value_2, _, _, _, _, _, _));
   }
 }
 
+TARGET_TEST_F(InterpreterAssemblerTest, GetSetContext) {
+  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);
+  }
+}
 
 TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
@@ -413,12 +438,11 @@
     EXPECT_THAT(
         reg_location_node,
         IsIntPtrAdd(
-            IsParameter(Linkage::kInterpreterRegisterFileParameter),
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
             IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -426,13 +450,13 @@
     Node* load_reg_node = m.LoadRegister(reg_index_node);
     EXPECT_THAT(
         load_reg_node,
-        m.IsLoad(MachineType::AnyTagged(),
-                 IsParameter(Linkage::kInterpreterRegisterFileParameter),
-                 IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
+        m.IsLoad(
+            MachineType::AnyTagged(),
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+            IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -441,15 +465,15 @@
     Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
     EXPECT_THAT(
         store_reg_node,
-        m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
-                                      kNoWriteBarrier),
-                  IsParameter(Linkage::kInterpreterRegisterFileParameter),
-                  IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2)),
-                  store_value));
+        m.IsStore(
+            StoreRepresentation(MachineRepresentation::kTagged,
+                                kNoWriteBarrier),
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+            IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2)),
+            store_value));
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -461,7 +485,6 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -472,7 +495,6 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -483,7 +505,6 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -493,7 +514,6 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -501,7 +521,7 @@
     Node* load_constant = m.LoadConstantPoolEntry(index);
     Matcher<Node*> constant_pool_matcher = m.IsLoad(
         MachineType::AnyTagged(),
-        IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
         IsIntPtrConstant(BytecodeArray::kConstantPoolOffset - kHeapObjectTag));
     EXPECT_THAT(
         load_constant,
@@ -512,7 +532,6 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, LoadFixedArrayElement) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -529,7 +548,6 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -542,7 +560,6 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -558,7 +575,6 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, StoreContextSlot) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
@@ -577,21 +593,22 @@
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
     Node* arg1 = m.Int32Constant(2);
     Node* arg2 = m.Int32Constant(3);
-    Node* call_runtime = m.CallRuntime(Runtime::kAdd, arg1, arg2);
+    Node* context =
+        m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+    Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
     EXPECT_THAT(
         call_runtime,
         IsCall(_, _, arg1, arg2, _, IsInt32Constant(2),
-               IsParameter(Linkage::kInterpreterContextParameter), _, _));
+               IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+               _));
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
   const int kResultSizes[] = {1, 2};
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
@@ -602,6 +619,8 @@
       Node* function_id = m.Int32Constant(0);
       Node* first_arg = m.Int32Constant(1);
       Node* arg_count = m.Int32Constant(2);
+      Node* context =
+          m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
 
       Matcher<Node*> function_table = IsExternalConstant(
           ExternalReference::runtime_function_table_address(isolate()));
@@ -612,63 +631,53 @@
           m.IsLoad(MachineType::Pointer(), function,
                    IsInt32Constant(offsetof(Runtime::Function, entry)));
 
-      Node* call_runtime =
-          m.CallRuntime(function_id, first_arg, arg_count, result_size);
+      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(Linkage::kInterpreterContextParameter), _, _));
+                 IsParameter(InterpreterDispatchDescriptor::kContextParameter),
+                 _, _));
     }
   }
 }
 
-
-TARGET_TEST_F(InterpreterAssemblerTest, CallIC) {
-  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
-    InterpreterAssemblerForTest m(this, bytecode);
-    LoadWithVectorDescriptor descriptor(isolate());
-    Node* target = m.Int32Constant(1);
-    Node* arg1 = m.Int32Constant(2);
-    Node* arg2 = m.Int32Constant(3);
-    Node* arg3 = m.Int32Constant(4);
-    Node* arg4 = m.Int32Constant(5);
-    Node* call_ic = m.CallIC(descriptor, target, arg1, arg2, arg3, arg4);
-    EXPECT_THAT(
-        call_ic,
-        IsCall(_, target, arg1, arg2, arg3, arg4,
-               IsParameter(Linkage::kInterpreterContextParameter), _, _));
-  }
-}
-
-
 TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
-  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
-    InterpreterAssemblerForTest m(this, bytecode);
-    Callable builtin = CodeFactory::InterpreterPushArgsAndCall(isolate());
-    Node* function = m.Int32Constant(0);
-    Node* first_arg = m.Int32Constant(1);
-    Node* arg_count = m.Int32Constant(2);
-    Node* call_js = m.CallJS(function, first_arg, arg_count);
-    EXPECT_THAT(
-        call_js,
-        IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
-               function, IsParameter(Linkage::kInterpreterContextParameter), _,
-               _));
+  TailCallMode tail_call_modes[] = {TailCallMode::kDisallow,
+                                    TailCallMode::kAllow};
+  TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) {
+    TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+      InterpreterAssemblerForTest m(this, bytecode);
+      Callable builtin =
+          CodeFactory::InterpreterPushArgsAndCall(isolate(), tail_call_mode);
+      Node* function = m.Int32Constant(0);
+      Node* first_arg = m.Int32Constant(1);
+      Node* arg_count = m.Int32Constant(2);
+      Node* context =
+          m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+      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),
+                 _, _));
+    }
   }
 }
 
-
 TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
     Node* feedback_vector = m.LoadTypeFeedbackVector();
 
-    Matcher<Node*> load_function_matcher =
-        m.IsLoad(MachineType::AnyTagged(),
-                 IsParameter(Linkage::kInterpreterRegisterFileParameter),
-                 IsIntPtrConstant(
-                     InterpreterFrameConstants::kFunctionFromRegisterPointer));
+    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 -
@@ -682,6 +691,6 @@
   }
 }
 
-}  // namespace compiler
+}  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/interpreter/interpreter-assembler-unittest.h b/test/unittests/interpreter/interpreter-assembler-unittest.h
new file mode 100644
index 0000000..321c724
--- /dev/null
+++ b/test/unittests/interpreter/interpreter-assembler-unittest.h
@@ -0,0 +1,57 @@
+// 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_INTERPRETER_ASSEMBLER_UNITTEST_H_
+#define V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
+
+#include "src/compiler/machine-operator.h"
+#include "src/interpreter/interpreter-assembler.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gmock-support.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+using ::testing::Matcher;
+
+class InterpreterAssemblerTest : public TestWithIsolateAndZone {
+ public:
+  InterpreterAssemblerTest() {}
+  ~InterpreterAssemblerTest() override {}
+
+  class InterpreterAssemblerForTest final : public InterpreterAssembler {
+   public:
+    InterpreterAssemblerForTest(InterpreterAssemblerTest* test,
+                                Bytecode bytecode)
+        : InterpreterAssembler(test->isolate(), test->zone(), bytecode) {}
+    ~InterpreterAssemblerForTest() override {}
+
+    Matcher<compiler::Node*> IsLoad(
+        const Matcher<compiler::LoadRepresentation>& rep_matcher,
+        const Matcher<compiler::Node*>& base_matcher,
+        const Matcher<compiler::Node*>& index_matcher);
+    Matcher<compiler::Node*> IsStore(
+        const Matcher<compiler::StoreRepresentation>& rep_matcher,
+        const Matcher<compiler::Node*>& base_matcher,
+        const Matcher<compiler::Node*>& index_matcher,
+        const Matcher<compiler::Node*>& value_matcher);
+
+    Matcher<compiler::Node*> IsBytecodeOperand(int offset);
+    Matcher<compiler::Node*> IsBytecodeOperandSignExtended(int offset);
+    Matcher<compiler::Node*> IsBytecodeOperandShort(int offset);
+    Matcher<compiler::Node*> IsBytecodeOperandShortSignExtended(int offset);
+
+    using InterpreterAssembler::graph;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(InterpreterAssemblerForTest);
+  };
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
diff --git a/test/unittests/interpreter/register-translator-unittest.cc b/test/unittests/interpreter/register-translator-unittest.cc
new file mode 100644
index 0000000..e9f65a6
--- /dev/null
+++ b/test/unittests/interpreter/register-translator-unittest.cc
@@ -0,0 +1,260 @@
+// 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 <stack>
+
+#include "src/v8.h"
+
+#include "src/interpreter/register-translator.h"
+#include "src/isolate.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class RegisterTranslatorTest : public TestWithIsolateAndZone,
+                               private RegisterMover {
+ public:
+  RegisterTranslatorTest() : translator_(this), move_count_(0) {
+    window_start_ =
+        RegisterTranslator::DistanceToTranslationWindow(Register(0));
+    window_width_ =
+        Register::MaxRegisterIndexForByteOperand() - window_start_ + 1;
+  }
+
+  ~RegisterTranslatorTest() override {}
+
+  bool PopMoveAndMatch(Register from, Register to) {
+    if (!moves_.empty()) {
+      CHECK(from.is_valid() && to.is_valid());
+      const std::pair<Register, Register> top = moves_.top();
+      moves_.pop();
+      return top.first == from && top.second == to;
+    } else {
+      return false;
+    }
+  }
+
+  int move_count() const { return move_count_; }
+  RegisterTranslator* translator() { return &translator_; }
+
+  int window_start() const { return window_start_; }
+  int window_width() const { return window_width_; }
+  int window_limit() const { return window_start_ + window_width_; }
+
+ protected:
+  static const char* const kBadOperandRegex;
+
+ private:
+  void MoveRegisterUntranslated(Register from, Register to) override {
+    moves_.push(std::make_pair(from, to));
+    move_count_++;
+  }
+
+  RegisterTranslator translator_;
+  std::stack<std::pair<Register, Register>> moves_;
+  int move_count_;
+  int window_start_;
+  int window_width_;
+};
+
+const char* const RegisterTranslatorTest::kBadOperandRegex =
+    ".*OperandType::kReg8 \\|\\| .*OperandType::kRegOut8\\) && "
+    "RegisterIsMovableToWindow.*";
+
+TEST_F(RegisterTranslatorTest, TestFrameSizeAdjustmentsForTranslationWindow) {
+  EXPECT_EQ(0, RegisterTranslator::RegisterCountAdjustment(0, 0));
+  EXPECT_EQ(0, RegisterTranslator::RegisterCountAdjustment(10, 10));
+  EXPECT_EQ(window_width(),
+            RegisterTranslator::RegisterCountAdjustment(173, 0));
+  EXPECT_EQ(window_width(),
+            RegisterTranslator::RegisterCountAdjustment(173, 137));
+  EXPECT_EQ(window_width(),
+            RegisterTranslator::RegisterCountAdjustment(173, 137));
+  // TODO(oth): Add a kMaxParameters8 that derives this info from the frame.
+  int param_limit = FLAG_enable_embedded_constant_pool ? 119 : 120;
+  EXPECT_EQ(0, RegisterTranslator::RegisterCountAdjustment(0, param_limit));
+  EXPECT_EQ(window_limit(),
+            RegisterTranslator::RegisterCountAdjustment(0, 128));
+  EXPECT_EQ(window_limit(),
+            RegisterTranslator::RegisterCountAdjustment(0, 129));
+  EXPECT_EQ(window_limit() - 32,
+            RegisterTranslator::RegisterCountAdjustment(32, 129));
+}
+
+TEST_F(RegisterTranslatorTest, TestInTranslationWindow) {
+  EXPECT_GE(window_start(), 0);
+  EXPECT_FALSE(
+      RegisterTranslator::InTranslationWindow(Register(window_start() - 1)));
+  EXPECT_TRUE(RegisterTranslator::InTranslationWindow(
+      Register(Register::MaxRegisterIndexForByteOperand())));
+  EXPECT_FALSE(RegisterTranslator::InTranslationWindow(
+      Register(Register::MaxRegisterIndexForByteOperand() + 1)));
+  for (int index = window_start(); index < window_limit(); index += 1) {
+    EXPECT_TRUE(RegisterTranslator::InTranslationWindow(Register(index)));
+  }
+}
+
+TEST_F(RegisterTranslatorTest, FitsInReg8Operand) {
+  EXPECT_GT(window_start(), 0);
+  EXPECT_TRUE(RegisterTranslator::FitsInReg8Operand(
+      Register::FromParameterIndex(0, 3)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg8Operand(
+      Register::FromParameterIndex(2, 3)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg8Operand(Register(0)));
+  EXPECT_TRUE(
+      RegisterTranslator::FitsInReg8Operand(Register(window_start() - 1)));
+  EXPECT_FALSE(RegisterTranslator::FitsInReg8Operand(Register(kMaxInt8)));
+  EXPECT_FALSE(RegisterTranslator::FitsInReg8Operand(Register(kMaxInt8 + 1)));
+  for (int index = window_start(); index < window_limit(); index += 1) {
+    EXPECT_FALSE(RegisterTranslator::FitsInReg8Operand(Register(index)));
+  }
+}
+
+TEST_F(RegisterTranslatorTest, FitsInReg16Operand) {
+  EXPECT_GT(window_start(), 0);
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+      Register::FromParameterIndex(0, 3)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+      Register::FromParameterIndex(2, 3)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+      Register::FromParameterIndex(0, 999)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+      Register::FromParameterIndex(0, Register::MaxParameterIndex() + 1)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(0)));
+  EXPECT_TRUE(
+      RegisterTranslator::FitsInReg16Operand(Register(window_start() - 1)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(kMaxInt8 + 1)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(kMaxInt8 + 2)));
+  for (int index = 0; index <= kMaxInt16 - window_width(); index += 1) {
+    EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(index)));
+  }
+  for (int index = Register::MaxRegisterIndex() - window_width() + 1;
+       index < Register::MaxRegisterIndex() + 2; index += 1) {
+    EXPECT_FALSE(RegisterTranslator::FitsInReg16Operand(Register(index)));
+  }
+}
+
+TEST_F(RegisterTranslatorTest, NoTranslationRequired) {
+  Register window_reg(window_start());
+  Register local_reg(57);
+  uint32_t operands[] = {local_reg.ToRawOperand()};
+  translator()->TranslateInputRegisters(Bytecode::kLdar, operands, 1);
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(0, move_count());
+
+  Register param_reg = Register::FromParameterIndex(129, 130);
+  operands[0] = param_reg.ToRawOperand();
+  translator()->TranslateInputRegisters(Bytecode::kAdd, operands, 1);
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(0, move_count());
+}
+
+TEST_F(RegisterTranslatorTest, TranslationRequired) {
+  Register window_reg(window_start());
+  Register local_reg(137);
+  Register local_reg_translated(local_reg.index() + window_width());
+
+  uint32_t operands[] = {local_reg.ToRawOperand()};
+  translator()->TranslateInputRegisters(Bytecode::kLdar, operands, 1);
+  EXPECT_EQ(1, move_count());
+  EXPECT_TRUE(PopMoveAndMatch(local_reg_translated, window_reg));
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(1, move_count());
+  EXPECT_FALSE(PopMoveAndMatch(window_reg, local_reg_translated));
+
+  operands[0] = local_reg.ToRawOperand();
+  translator()->TranslateInputRegisters(Bytecode::kStar, operands, 1);
+  EXPECT_EQ(1, move_count());
+  EXPECT_FALSE(PopMoveAndMatch(local_reg_translated, window_reg));
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(2, move_count());
+  EXPECT_TRUE(PopMoveAndMatch(window_reg, local_reg_translated));
+
+  Register param_reg = Register::FromParameterIndex(0, 130);
+  operands[0] = {param_reg.ToRawOperand()};
+  translator()->TranslateInputRegisters(Bytecode::kLdar, operands, 1);
+  EXPECT_EQ(3, move_count());
+  EXPECT_TRUE(PopMoveAndMatch(param_reg, window_reg));
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(3, move_count());
+  EXPECT_FALSE(PopMoveAndMatch(window_reg, param_reg));
+
+  operands[0] = {param_reg.ToRawOperand()};
+  translator()->TranslateInputRegisters(Bytecode::kStar, operands, 1);
+  EXPECT_EQ(3, move_count());
+  EXPECT_FALSE(PopMoveAndMatch(local_reg_translated, window_reg));
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(4, move_count());
+  EXPECT_TRUE(PopMoveAndMatch(window_reg, param_reg));
+}
+
+TEST_F(RegisterTranslatorTest, RangeTranslation) {
+  Register window0(window_start());
+  Register window1(window_start() + 1);
+  Register window2(window_start() + 2);
+  uint32_t operands[3];
+
+  // Bytecode::kNew with valid range operand.
+  Register constructor0(0);
+  Register args0(1);
+  operands[0] = constructor0.ToRawOperand();
+  operands[1] = args0.ToRawOperand();
+  operands[2] = 1;
+  translator()->TranslateInputRegisters(Bytecode::kNew, operands, 3);
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(0, move_count());
+
+  // Bytecode::kNewWide with valid range operand.
+  Register constructor1(128);
+  Register constructor1_translated(constructor1.index() + window_width());
+  Register args1(129);
+  Register args1_translated(args1.index() + window_width());
+  operands[0] = constructor1.ToRawOperand();
+  operands[1] = args1.ToRawOperand();
+  operands[2] = 3;
+  translator()->TranslateInputRegisters(Bytecode::kNewWide, operands, 3);
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(0, move_count());
+}
+
+TEST_F(RegisterTranslatorTest, BadRange0) {
+  // Bytecode::kNew with invalid range operand (kMaybeReg8).
+  Register constructor1(128);
+  Register args1(129);
+  uint32_t operands[] = {constructor1.ToRawOperand(), args1.ToRawOperand(), 3};
+  ASSERT_DEATH_IF_SUPPORTED(
+      translator()->TranslateInputRegisters(Bytecode::kNew, operands, 3),
+      kBadOperandRegex);
+}
+
+TEST_F(RegisterTranslatorTest, BadRange1) {
+  // Bytecode::kForInPrepare with invalid range operand (kRegTriple8)
+  Register for_in_state(160);
+  Register for_in_state_translated(for_in_state.index() + window_width());
+  uint32_t operands[] = {for_in_state.ToRawOperand()};
+  ASSERT_DEATH_IF_SUPPORTED(translator()->TranslateInputRegisters(
+                                Bytecode::kForInPrepare, operands, 1),
+                            kBadOperandRegex);
+}
+
+TEST_F(RegisterTranslatorTest, BadRange2) {
+  // Bytecode::kForInNext with invalid range operand (kRegPair8)
+  Register receiver(192);
+  Register receiver_translated(receiver.index() + window_width());
+  Register index(193);
+  Register index_translated(index.index() + window_width());
+  Register cache_info_pair(194);
+  Register cache_info_pair_translated(cache_info_pair.index() + window_width());
+  uint32_t operands[] = {receiver.ToRawOperand(), index.ToRawOperand(),
+                         cache_info_pair.ToRawOperand()};
+  ASSERT_DEATH_IF_SUPPORTED(
+      translator()->TranslateInputRegisters(Bytecode::kForInNext, operands, 3),
+      kBadOperandRegex);
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/runtime/runtime-interpreter-unittest.cc b/test/unittests/runtime/runtime-interpreter-unittest.cc
index 97b7992..c10ddcd 100644
--- a/test/unittests/runtime/runtime-interpreter-unittest.cc
+++ b/test/unittests/runtime/runtime-interpreter-unittest.cc
@@ -23,12 +23,6 @@
 
   bool TestOperatorWithObjects(RuntimeMethod method, Handle<Object> lhs,
                                Handle<Object> rhs, bool expected);
-  bool TestOperator(RuntimeMethod method, int32_t lhs, int32_t rhs,
-                    bool expected);
-  bool TestOperator(RuntimeMethod method, double lhs, double rhs,
-                    bool expected);
-  bool TestOperator(RuntimeMethod method, const char* lhs, const char* rhs,
-                    bool expected);
 };
 
 
@@ -44,99 +38,6 @@
 }
 
 
-bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, int32_t lhs,
-                                          int32_t rhs, bool expected) {
-  Handle<Object> x = isolate()->factory()->NewNumberFromInt(lhs);
-  Handle<Object> y = isolate()->factory()->NewNumberFromInt(rhs);
-  return TestOperatorWithObjects(method, x, y, expected);
-}
-
-
-bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, double lhs,
-                                          double rhs, bool expected) {
-  Handle<Object> x = isolate()->factory()->NewNumber(lhs);
-  Handle<Object> y = isolate()->factory()->NewNumber(rhs);
-  CHECK_EQ(HeapNumber::cast(*x)->value(), lhs);
-  CHECK_EQ(HeapNumber::cast(*y)->value(), rhs);
-  return TestOperatorWithObjects(method, x, y, expected);
-}
-
-
-bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, const char* lhs,
-                                          const char* rhs, bool expected) {
-  Handle<Object> x = isolate()->factory()->NewStringFromAsciiChecked(lhs);
-  Handle<Object> y = isolate()->factory()->NewStringFromAsciiChecked(rhs);
-  return TestOperatorWithObjects(method, x, y, expected);
-}
-
-
-TEST_F(RuntimeInterpreterTest, TestOperatorsWithIntegers) {
-  int32_t inputs[] = {kMinInt, Smi::kMinValue, -17,    -1, 0, 1,
-                      991,     Smi::kMaxValue, kMaxInt};
-  TRACED_FOREACH(int, lhs, inputs) {
-    TRACED_FOREACH(int, rhs, inputs) {
-#define INTEGER_OPERATOR_CHECK(r, op, x, y) \
-  CHECK(TestOperator(Runtime_Interpreter##r, x, y, x op y))
-      INTEGER_OPERATOR_CHECK(Equals, ==, lhs, rhs);
-      INTEGER_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
-      INTEGER_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
-      INTEGER_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
-      INTEGER_OPERATOR_CHECK(LessThan, <, lhs, rhs);
-      INTEGER_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
-      INTEGER_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
-      INTEGER_OPERATOR_CHECK(GreaterThanOrEqual, >=, lhs, rhs);
-#undef INTEGER_OPERATOR_CHECK
-    }
-  }
-}
-
-
-TEST_F(RuntimeInterpreterTest, TestOperatorsWithDoubles) {
-  double inputs[] = {std::numeric_limits<double>::min(),
-                     std::numeric_limits<double>::max(),
-                     -0.001,
-                     0.01,
-                     3.14,
-                     -6.02214086e23};
-  TRACED_FOREACH(double, lhs, inputs) {
-    TRACED_FOREACH(double, rhs, inputs) {
-#define DOUBLE_OPERATOR_CHECK(r, op, x, y) \
-  CHECK(TestOperator(Runtime_Interpreter##r, x, y, x op y))
-      DOUBLE_OPERATOR_CHECK(Equals, ==, lhs, rhs);
-      DOUBLE_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
-      DOUBLE_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
-      DOUBLE_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
-      DOUBLE_OPERATOR_CHECK(LessThan, <, lhs, rhs);
-      DOUBLE_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
-      DOUBLE_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
-      DOUBLE_OPERATOR_CHECK(GreaterThanOrEqual, >=, lhs, rhs);
-#undef DOUBLE_OPERATOR_CHECK
-    }
-  }
-}
-
-
-TEST_F(RuntimeInterpreterTest, TestOperatorsWithString) {
-  const char* inputs[] = {"abc", "a", "def", "0"};
-  TRACED_FOREACH(const char*, lhs, inputs) {
-    TRACED_FOREACH(const char*, rhs, inputs) {
-#define STRING_OPERATOR_CHECK(r, op, x, y)         \
-  CHECK(TestOperator(Runtime_Interpreter##r, x, y, \
-                     std::string(x) op std::string(y)))
-      STRING_OPERATOR_CHECK(Equals, ==, lhs, rhs);
-      STRING_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
-      STRING_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
-      STRING_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
-      STRING_OPERATOR_CHECK(LessThan, <, lhs, rhs);
-      STRING_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
-      STRING_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
-      STRING_OPERATOR_CHECK(GreaterThanOrEqual, >=, lhs, rhs);
-#undef STRING_OPERATOR_CHECK
-    }
-  }
-}
-
-
 TEST_F(RuntimeInterpreterTest, ToBoolean) {
   double quiet_nan = std::numeric_limits<double>::quiet_NaN();
   std::pair<Handle<Object>, bool> cases[] = {
diff --git a/test/unittests/unittests.gyp b/test/unittests/unittests.gyp
index 5339da3..638fd84 100644
--- a/test/unittests/unittests.gyp
+++ b/test/unittests/unittests.gyp
@@ -60,10 +60,9 @@
         'compiler/instruction-selector-unittest.h',
         'compiler/instruction-sequence-unittest.cc',
         'compiler/instruction-sequence-unittest.h',
-        'compiler/interpreter-assembler-unittest.cc',
-        'compiler/interpreter-assembler-unittest.h',
+        'compiler/int64-lowering-unittest.cc',
         'compiler/js-builtin-reducer-unittest.cc',
-        'compiler/js-context-relaxation-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',
@@ -86,6 +85,7 @@
         'compiler/schedule-unittest.cc',
         'compiler/select-lowering-unittest.cc',
         'compiler/scheduler-unittest.cc',
+        'compiler/scheduler-rpo-unittest.cc',
         'compiler/simplified-operator-reducer-unittest.cc',
         'compiler/simplified-operator-unittest.cc',
         'compiler/state-values-utils-unittest.cc',
@@ -99,6 +99,9 @@
         'interpreter/bytecode-array-iterator-unittest.cc',
         'interpreter/bytecode-register-allocator-unittest.cc',
         'interpreter/constant-array-builder-unittest.cc',
+        'interpreter/interpreter-assembler-unittest.cc',
+        'interpreter/interpreter-assembler-unittest.h',
+        'interpreter/register-translator-unittest.cc',
         'libplatform/default-platform-unittest.cc',
         'libplatform/task-queue-unittest.cc',
         'libplatform/worker-thread-unittest.cc',
@@ -107,6 +110,7 @@
         'heap/memory-reducer-unittest.cc',
         'heap/heap-unittest.cc',
         'heap/scavenge-job-unittest.cc',
+        'heap/slot-set-unittest.cc',
         'locked-queue-unittest.cc',
         'run-all-unittests.cc',
         'runtime/runtime-interpreter-unittest.cc',
@@ -114,6 +118,7 @@
         'test-utils.cc',
         'wasm/ast-decoder-unittest.cc',
         'wasm/encoder-unittest.cc',
+        'wasm/loop-assignment-analysis-unittest.cc',
         'wasm/module-decoder-unittest.cc',
         'wasm/wasm-macro-gen-unittest.cc',
       ],
diff --git a/test/unittests/wasm/ast-decoder-unittest.cc b/test/unittests/wasm/ast-decoder-unittest.cc
index 923c554..6721587 100644
--- a/test/unittests/wasm/ast-decoder-unittest.cc
+++ b/test/unittests/wasm/ast-decoder-unittest.cc
@@ -35,6 +35,8 @@
     kExprI32Shl,  kExprI32ShrU, kExprI32ShrS, kExprI32Eq,   kExprI32LtS,
     kExprI32LeS,  kExprI32LtU,  kExprI32LeU};
 
+#define WASM_BRV_IF_ZERO(depth, val) \
+  kExprBrIf, static_cast<byte>(depth), val, WASM_ZERO
 
 #define EXPECT_VERIFIES(env, x) Verify(kSuccess, env, x, x + arraysize(x))
 
@@ -87,10 +89,10 @@
   static void init_env(FunctionEnv* env, FunctionSig* sig) {
     env->module = nullptr;
     env->sig = sig;
-    env->local_int32_count = 0;
-    env->local_int64_count = 0;
-    env->local_float32_count = 0;
-    env->local_float64_count = 0;
+    env->local_i32_count = 0;
+    env->local_i64_count = 0;
+    env->local_f32_count = 0;
+    env->local_f64_count = 0;
     env->SumLocals();
   }
 
@@ -179,9 +181,9 @@
   FunctionEnv env;
   env.module = nullptr;
   env.sig = sig;
-  env.local_int32_count = count;
-  env.local_float64_count = 0;
-  env.local_float32_count = 0;
+  env.local_i32_count = count;
+  env.local_f64_count = 0;
+  env.local_f32_count = 0;
   env.total_locals = static_cast<unsigned>(count + sig->parameter_count());
   return env;
 }
@@ -251,9 +253,6 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, Float32Const) {
   byte code[] = {kExprF32Const, 0, 0, 0, 0};
   float* ptr = reinterpret_cast<float*>(code + 1);
@@ -273,8 +272,6 @@
   }
 }
 
-#endif
-
 
 TEST_F(WasmDecoderTest, Int32Const_off_end) {
   byte code[] = {kExprI32Const, 0xaa, 0xbb, 0xcc, 0x44};
@@ -338,7 +335,7 @@
 
 
 TEST_F(WasmDecoderTest, GetLocal_varint) {
-  env_i_i.local_int32_count = 1000000000;
+  env_i_i.local_i32_count = 1000000000;
   env_i_i.total_locals += 1000000000;
 
   {
@@ -532,16 +529,11 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, ExprBlock1c) {
   static const byte code[] = {kExprBlock, 1, kExprF32Const, 0, 0, 0, 0};
   EXPECT_VERIFIES(&env_f_ff, code);
 }
 
-#endif
-
 
 TEST_F(WasmDecoderTest, IfEmpty) {
   static const byte code[] = {kExprIf, kExprGetLocal, 0, kExprNop};
@@ -704,9 +696,6 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, ReturnVoid3) {
   EXPECT_VERIFIES_INLINE(&env_v_v, kExprI8Const, 0);
   EXPECT_VERIFIES_INLINE(&env_v_v, kExprI32Const, 0, 0, 0, 0);
@@ -717,8 +706,6 @@
   EXPECT_VERIFIES_INLINE(&env_v_i, kExprGetLocal, 0);
 }
 
-#endif
-
 
 TEST_F(WasmDecoderTest, Unreachable1) {
   EXPECT_VERIFIES_INLINE(&env_v_v, kExprUnreachable);
@@ -881,9 +868,6 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, MacrosBreak) {
   EXPECT_VERIFIES_INLINE(&env_v_v, WASM_LOOP(1, WASM_BREAK(0)));
 
@@ -895,8 +879,6 @@
                          WASM_LOOP(1, WASM_BREAKV(0, WASM_F64(0.0))));
 }
 
-#endif
-
 
 TEST_F(WasmDecoderTest, MacrosContinue) {
   EXPECT_VERIFIES_INLINE(&env_v_v, WASM_LOOP(1, WASM_CONTINUE(0)));
@@ -1204,14 +1186,13 @@
 class TestModuleEnv : public ModuleEnv {
  public:
   TestModuleEnv() {
-    mem_start = 0;
-    mem_end = 0;
+    instance = nullptr;
     module = &mod;
     linker = nullptr;
-    function_code = nullptr;
     mod.globals = new std::vector<WasmGlobal>;
     mod.signatures = new std::vector<FunctionSig*>;
     mod.functions = new std::vector<WasmFunction>;
+    mod.import_table = new std::vector<WasmImport>;
   }
   byte AddGlobal(MachineType mem_type) {
     mod.globals->push_back({0, mem_type, 0, false});
@@ -1228,6 +1209,11 @@
     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});
+    CHECK(mod.import_table->size() <= 127);
+    return static_cast<byte>(mod.import_table->size() - 1);
+  }
 
  private:
   WasmModule mod;
@@ -1265,9 +1251,6 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, CallsWithSpilloverArgs) {
   static LocalType a_i_ff[] = {kAstI32, kAstF32, kAstF32};
   FunctionSig sig_i_ff(1, 2, a_i_ff);
@@ -1331,8 +1314,6 @@
   EXPECT_FAILURE_INLINE(env, WASM_CALL_FUNCTION(1, WASM_F32(17.6)));
 }
 
-#endif
-
 
 TEST_F(WasmDecoderTest, SimpleIndirectCalls) {
   FunctionEnv* env = &env_i_i;
@@ -1389,6 +1370,39 @@
   EXPECT_FAILURE_INLINE(env, WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_F32(17.6)));
 }
 
+TEST_F(WasmDecoderTest, SimpleImportCalls) {
+  FunctionEnv* env = &env_i_i;
+  TestModuleEnv module_env;
+  env->module = &module_env;
+
+  byte f0 = module_env.AddImport(sigs.i_v());
+  byte f1 = module_env.AddImport(sigs.i_i());
+  byte f2 = module_env.AddImport(sigs.i_ii());
+
+  EXPECT_VERIFIES_INLINE(env, WASM_CALL_IMPORT0(f0));
+  EXPECT_VERIFIES_INLINE(env, WASM_CALL_IMPORT(f1, WASM_I8(22)));
+  EXPECT_VERIFIES_INLINE(env, WASM_CALL_IMPORT(f2, WASM_I8(32), WASM_I8(72)));
+}
+
+TEST_F(WasmDecoderTest, ImportCallsWithMismatchedSigs3) {
+  FunctionEnv* env = &env_i_i;
+  TestModuleEnv module_env;
+  env->module = &module_env;
+
+  byte f0 = module_env.AddImport(sigs.i_f());
+
+  EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT0(f0));
+  EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f0, WASM_I8(17)));
+  EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f0, WASM_I64(27)));
+  EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f0, WASM_F64(37.2)));
+
+  byte f1 = module_env.AddImport(sigs.i_d());
+
+  EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT0(f1));
+  EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f1, WASM_I8(16)));
+  EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f1, WASM_I64(16)));
+  EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f1, WASM_F32(17.6)));
+}
 
 TEST_F(WasmDecoderTest, Int32Globals) {
   FunctionEnv* env = &env_i_i;
@@ -1575,27 +1589,21 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, BreaksWithMultipleTypes) {
   EXPECT_FAILURE_INLINE(
-      &env_i_i,
-      WASM_BLOCK(2, WASM_BRV_IF(0, WASM_ZERO, WASM_I8(7)), WASM_F32(7.7)));
-  EXPECT_FAILURE_INLINE(&env_i_i,
-                        WASM_BLOCK(2, WASM_BRV_IF(0, WASM_ZERO, WASM_I8(7)),
-                                   WASM_BRV_IF(0, WASM_ZERO, WASM_F32(7.7))));
-  EXPECT_FAILURE_INLINE(&env_i_i,
-                        WASM_BLOCK(3, WASM_BRV_IF(0, WASM_ZERO, WASM_I8(8)),
-                                   WASM_BRV_IF(0, WASM_ZERO, WASM_I8(0)),
-                                   WASM_BRV_IF(0, WASM_ZERO, WASM_F32(7.7))));
-  EXPECT_FAILURE_INLINE(&env_i_i,
-                        WASM_BLOCK(3, WASM_BRV_IF(0, WASM_ZERO, WASM_I8(9)),
-                                   WASM_BRV_IF(0, WASM_ZERO, WASM_F32(7.7)),
-                                   WASM_BRV_IF(0, WASM_ZERO, WASM_I8(11))));
-}
+      &env_i_i, WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_I8(7)), WASM_F32(7.7)));
 
-#endif
+  EXPECT_FAILURE_INLINE(&env_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(&env_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(&env_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))));
+}
 
 
 TEST_F(WasmDecoderTest, BreakNesting_6_levels) {
@@ -1630,9 +1638,6 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, ExprBreak_TypeCheck) {
   FunctionEnv* envs[] = {&env_i_i, &env_l_l, &env_f_ff, &env_d_dd};
   for (size_t i = 0; i < arraysize(envs); i++) {
@@ -1655,17 +1660,14 @@
                  WASM_F64(1.2)));
 }
 
-#endif
-
 
 TEST_F(WasmDecoderTest, 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(0, WASM_ZERO, 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))};
 
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
     for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
@@ -1715,37 +1717,42 @@
   }
 }
 
-
-TEST_F(WasmDecoderTest, ExprBrIf_type) {
-  EXPECT_VERIFIES_INLINE(
-      &env_i_i,
-      WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)),
-                 WASM_GET_LOCAL(0)));
-  EXPECT_FAILURE_INLINE(
-      &env_d_dd,
-      WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)),
-                 WASM_GET_LOCAL(0)));
-
+TEST_F(WasmDecoderTest, ExprBrIf_cond_type) {
   FunctionEnv env;
+  byte code[] = {
+      WASM_BLOCK(1, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))};
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
-    LocalType type = kLocalTypes[i];
-    LocalType storage[] = {kAstI32, kAstI32, type};
-    FunctionSig sig(1, 2, storage);
-    init_env(&env, &sig);  // (i32, X) -> i32
+    for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
+      LocalType types[] = {kLocalTypes[i], kLocalTypes[j]};
+      FunctionSig sig(0, 2, types);
+      init_env(&env, &sig);
 
-    byte code1[] = {
-        WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)),
-                   WASM_GET_LOCAL(0))};
+      if (types[1] == kAstI32) {
+        EXPECT_VERIFIES(&env, code);
+      } else {
+        EXPECT_FAILURE(&env, code);
+      }
+    }
+  }
+}
 
-    byte code2[] = {
-        WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(1), WASM_GET_LOCAL(0)),
-                   WASM_GET_LOCAL(0))};
-    if (type == kAstI32) {
-      EXPECT_VERIFIES(&env, code1);
-      EXPECT_VERIFIES(&env, code2);
-    } else {
-      EXPECT_FAILURE(&env, code1);
-      EXPECT_FAILURE(&env, code2);
+TEST_F(WasmDecoderTest, ExprBrIf_val_type) {
+  FunctionEnv env;
+  byte code[] = {
+      WASM_BLOCK(2, 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],
+                           kAstI32};
+      FunctionSig sig(1, 3, types);
+      init_env(&env, &sig);
+
+      if (i == j) {
+        EXPECT_VERIFIES(&env, code);
+      } else {
+        EXPECT_FAILURE(&env, code);
+      }
     }
   }
 }
@@ -1761,13 +1768,10 @@
       FunctionSig sig(1, 2, storage);
       init_env(&env, &sig);  // (i32, X) -> i32
 
-      byte code1[] = {
-          WASM_BLOCK(2, WASM_BRV_IF(0, WASM_ZERO, WASM_GET_LOCAL(which)),
-                     WASM_GET_LOCAL(which ^ 1))};
-      byte code2[] = {
-          WASM_LOOP(2, WASM_BRV_IF(1, WASM_ZERO, WASM_GET_LOCAL(which)),
-                    WASM_GET_LOCAL(which ^ 1))};
-
+      byte code1[] = {WASM_BLOCK(2, 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))};
 
       if (type == kAstI32) {
         EXPECT_VERIFIES(&env, code1);
@@ -1800,6 +1804,12 @@
   EXPECT_VERIFIES(&env_v_v, code);
 }
 
+TEST_F(WasmDecoderTest, TableSwitch0d) {
+  static byte code[] = {
+      WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), WASM_CASE_BR(1)),
+                 WASM_I8(67))};
+  EXPECT_VERIFIES(&env_v_v, code);
+}
 
 TEST_F(WasmDecoderTest, TableSwitch1) {
   static byte code[] = {WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)),
@@ -1831,9 +1841,6 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, TableSwitch1b) {
   EXPECT_VERIFIES_INLINE(&env_i_i, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)),
                          WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_ZERO));
@@ -1845,29 +1852,25 @@
                          WASM_TABLESWITCH_BODY(WASM_ZERO, WASM_F64(0.0)));
 }
 
-#endif
-
-
-TEST_F(WasmDecoderTest, TableSwitch_br) {
-  EXPECT_VERIFIES_INLINE(&env_i_i, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(0)),
-                         WASM_GET_LOCAL(0));
+TEST_F(WasmDecoderTest, TableSwitch_br1) {
   for (int depth = 0; depth < 2; depth++) {
-    EXPECT_VERIFIES_INLINE(
-        &env_i_i, WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)),
-                             WASM_GET_LOCAL(0)));
+    byte code[] = {WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)),
+                              WASM_GET_LOCAL(0))};
+    EXPECT_VERIFIES(&env_v_i, code);
+    EXPECT_FAILURE(&env_i_i, code);
   }
 }
 
 
 TEST_F(WasmDecoderTest, TableSwitch_invalid_br) {
   for (int depth = 1; depth < 4; depth++) {
-    EXPECT_FAILURE_INLINE(&env_i_i,
+    EXPECT_FAILURE_INLINE(&env_v_i,
                           WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)),
                           WASM_GET_LOCAL(0));
     EXPECT_FAILURE_INLINE(
-        &env_i_i,
-        WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth + 1)),
-                   WASM_GET_LOCAL(0)));
+        &env_v_i,
+        WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(depth), WASM_CASE_BR(depth)),
+        WASM_GET_LOCAL(0));
   }
 }
 
@@ -1880,17 +1883,12 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, TableSwitch1_br) {
   EXPECT_VERIFIES_INLINE(
       &env_i_i, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)),
       WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_ZERO)));
 }
 
-#endif
-
 
 TEST_F(WasmDecoderTest, TableSwitch2_br) {
   EXPECT_VERIFIES_INLINE(
@@ -1914,9 +1912,6 @@
 }
 
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
 TEST_F(WasmDecoderTest, ExprBreakNesting1) {
   EXPECT_VERIFIES_INLINE(&env_v_v, WASM_BLOCK(1, WASM_BRV(0, WASM_ZERO)));
   EXPECT_VERIFIES_INLINE(&env_v_v, WASM_BLOCK(1, WASM_BR(0)));
@@ -1934,18 +1929,56 @@
   EXPECT_VERIFIES_INLINE(&env_v_v, WASM_LOOP(1, WASM_BR(1)));
 }
 
-#endif
-
 
 TEST_F(WasmDecoderTest, Select) {
   EXPECT_VERIFIES_INLINE(
-      &env_i_i,
-      WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+      &env_i_i, WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_ZERO));
+  EXPECT_VERIFIES_INLINE(&env_f_ff,
+                         WASM_SELECT(WASM_F32(0.0), WASM_F32(0.0), WASM_ZERO));
+  EXPECT_VERIFIES_INLINE(&env_d_dd,
+                         WASM_SELECT(WASM_F64(0.0), WASM_F64(0.0), WASM_ZERO));
+  EXPECT_VERIFIES_INLINE(&env_l_l,
+                         WASM_SELECT(WASM_I64(0), WASM_I64(0), WASM_ZERO));
 }
 
+TEST_F(WasmDecoderTest, Select_fail1) {
+  EXPECT_FAILURE_INLINE(&env_i_i, WASM_SELECT(WASM_F32(0.0), WASM_GET_LOCAL(0),
+                                              WASM_GET_LOCAL(0)));
+  EXPECT_FAILURE_INLINE(&env_i_i, WASM_SELECT(WASM_GET_LOCAL(0), WASM_F32(0.0),
+                                              WASM_GET_LOCAL(0)));
+  EXPECT_FAILURE_INLINE(
+      &env_i_i,
+      WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_F32(0.0)));
+}
 
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
+TEST_F(WasmDecoderTest, Select_fail2) {
+  for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
+    LocalType type = kLocalTypes[i];
+    if (type == kAstI32) continue;
+
+    LocalType types[] = {type, kAstI32, type};
+    FunctionSig sig(1, 2, types);
+    FunctionEnv env;
+    init_env(&env, &sig);
+
+    EXPECT_VERIFIES_INLINE(
+        &env,
+        WASM_SELECT(WASM_GET_LOCAL(1), WASM_GET_LOCAL(1), WASM_GET_LOCAL(0)));
+
+    EXPECT_FAILURE_INLINE(
+        &env,
+        WASM_SELECT(WASM_GET_LOCAL(1), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+
+    EXPECT_FAILURE_INLINE(
+        &env,
+        WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), WASM_GET_LOCAL(0)));
+
+    EXPECT_FAILURE_INLINE(
+        &env,
+        WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  }
+}
+
 
 TEST_F(WasmDecoderTest, Select_TypeCheck) {
   EXPECT_FAILURE_INLINE(&env_i_i, WASM_SELECT(WASM_F32(9.9), WASM_GET_LOCAL(0),
@@ -1958,22 +1991,18 @@
       &env_i_i, WASM_SELECT(WASM_F32(9.9), WASM_GET_LOCAL(0), WASM_I64(0)));
 }
 
-#endif
-
 
 class WasmOpcodeLengthTest : public TestWithZone {
  public:
   WasmOpcodeLengthTest() : TestWithZone() {}
 };
 
-
-#define EXPECT_LENGTH(expected, opcode)                          \
-  {                                                              \
-    static const byte code[] = {opcode, 0, 0, 0, 0, 0, 0, 0, 0}; \
-    EXPECT_EQ(expected, OpcodeLength(code));                     \
+#define EXPECT_LENGTH(expected, opcode)                           \
+  {                                                               \
+    static const byte code[] = {opcode, 0, 0, 0, 0, 0, 0, 0, 0};  \
+    EXPECT_EQ(expected, OpcodeLength(code, code + sizeof(code))); \
   }
 
-
 TEST_F(WasmOpcodeLengthTest, Statements) {
   EXPECT_LENGTH(1, kExprNop);
   EXPECT_LENGTH(2, kExprBlock);
@@ -1997,6 +2026,7 @@
   EXPECT_LENGTH(2, kExprLoadGlobal);
   EXPECT_LENGTH(2, kExprStoreGlobal);
   EXPECT_LENGTH(2, kExprCallFunction);
+  EXPECT_LENGTH(2, kExprCallImport);
   EXPECT_LENGTH(2, kExprCallIndirect);
   EXPECT_LENGTH(1, kExprIf);
   EXPECT_LENGTH(1, kExprIfElse);
@@ -2014,11 +2044,11 @@
   byte size5[] = {kExprLoadGlobal, 1 | 0x80, 2 | 0x80, 3 | 0x80, 4};
   byte size6[] = {kExprLoadGlobal, 1 | 0x80, 2 | 0x80, 3 | 0x80, 4 | 0x80, 5};
 
-  EXPECT_EQ(2, OpcodeLength(size2));
-  EXPECT_EQ(3, OpcodeLength(size3));
-  EXPECT_EQ(4, OpcodeLength(size4));
-  EXPECT_EQ(5, OpcodeLength(size5));
-  EXPECT_EQ(6, OpcodeLength(size6));
+  EXPECT_EQ(2, OpcodeLength(size2, size2 + sizeof(size2)));
+  EXPECT_EQ(3, OpcodeLength(size3, size3 + sizeof(size3)));
+  EXPECT_EQ(4, OpcodeLength(size4, size4 + sizeof(size4)));
+  EXPECT_EQ(5, OpcodeLength(size5, size5 + sizeof(size5)));
+  EXPECT_EQ(6, OpcodeLength(size6, size6 + sizeof(size6)));
 }
 
 
@@ -2183,14 +2213,12 @@
   WasmOpcodeArityTest() : TestWithZone() {}
 };
 
-
-#define EXPECT_ARITY(expected, ...)               \
-  {                                               \
-    static const byte code[] = {__VA_ARGS__};     \
-    EXPECT_EQ(expected, OpcodeArity(&env, code)); \
+#define EXPECT_ARITY(expected, ...)                                    \
+  {                                                                    \
+    static const byte code[] = {__VA_ARGS__};                          \
+    EXPECT_EQ(expected, OpcodeArity(&env, code, code + sizeof(code))); \
   }
 
-
 TEST_F(WasmOpcodeArityTest, Control) {
   FunctionEnv env;
   EXPECT_ARITY(0, kExprNop);
@@ -2249,12 +2277,16 @@
   module.AddSignature(sigs.f_ff());
   module.AddSignature(sigs.i_d());
 
+  module.AddImport(sigs.f_ff());
+  module.AddImport(sigs.i_d());
+
   {
     FunctionEnv env;
     WasmDecoderTest::init_env(&env, sigs.i_ii());
     env.module = &module;
 
     EXPECT_ARITY(2, kExprCallFunction, 0);
+    EXPECT_ARITY(2, kExprCallImport, 0);
     EXPECT_ARITY(3, kExprCallIndirect, 0);
     EXPECT_ARITY(1, kExprBr);
     EXPECT_ARITY(2, kExprBrIf);
@@ -2266,6 +2298,7 @@
     env.module = &module;
 
     EXPECT_ARITY(1, kExprCallFunction, 1);
+    EXPECT_ARITY(1, kExprCallImport, 1);
     EXPECT_ARITY(2, kExprCallIndirect, 1);
     EXPECT_ARITY(1, kExprBr);
     EXPECT_ARITY(2, kExprBrIf);
diff --git a/test/unittests/wasm/encoder-unittest.cc b/test/unittests/wasm/encoder-unittest.cc
index 156cf6b..e09e71a 100644
--- a/test/unittests/wasm/encoder-unittest.cc
+++ b/test/unittests/wasm/encoder-unittest.cc
@@ -56,28 +56,28 @@
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint16_t f_index = builder->AddFunction();
   WasmFunctionBuilder* function = builder->FunctionAt(f_index);
-  uint16_t local_float32 = function->AddLocal(kAstF32);
+  uint16_t local_f32 = function->AddLocal(kAstF32);
   uint16_t param_float32 = function->AddParam(kAstF32);
-  uint16_t local_int32 = function->AddLocal(kAstI32);
-  uint16_t local_float64 = function->AddLocal(kAstF64);
-  uint16_t local_int64 = function->AddLocal(kAstI64);
+  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_int32_2 = function->AddLocal(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_int32);
+  code[1] = static_cast<uint8_t>(local_i32);
   function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(local_int32_2);
+  code[1] = static_cast<uint8_t>(local_i32_2);
   function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(local_int64);
+  code[1] = static_cast<uint8_t>(local_i64);
   function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(local_float32);
+  code[1] = static_cast<uint8_t>(local_f32);
   function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(local_float64);
+  code[1] = static_cast<uint8_t>(local_f64);
   function->EmitCode(code, sizeof(code), local_indices, 1);
 
   WasmFunctionEncoder* f = function->Build(&zone, builder);
diff --git a/test/unittests/wasm/loop-assignment-analysis-unittest.cc b/test/unittests/wasm/loop-assignment-analysis-unittest.cc
new file mode 100644
index 0000000..9586219
--- /dev/null
+++ b/test/unittests/wasm/loop-assignment-analysis-unittest.cc
@@ -0,0 +1,211 @@
+// Copyright 2016 the V8 project 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/v8.h"
+
+#include "test/cctest/wasm/test-signatures.h"
+
+#include "src/bit-vector.h"
+#include "src/objects.h"
+
+#include "src/wasm/ast-decoder.h"
+#include "src/wasm/wasm-macro-gen.h"
+#include "src/wasm/wasm-module.h"
+
+#define WASM_SET_ZERO(i) WASM_SET_LOCAL(i, WASM_ZERO)
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+class WasmLoopAssignmentAnalyzerTest : public TestWithZone {
+ public:
+  WasmLoopAssignmentAnalyzerTest() : TestWithZone(), sigs() {
+    init_env(&env, sigs.v_v());
+  }
+
+  TestSignatures sigs;
+  FunctionEnv env;
+
+  static void init_env(FunctionEnv* env, FunctionSig* sig) {
+    env->module = nullptr;
+    env->sig = sig;
+    env->local_i32_count = 0;
+    env->local_i64_count = 0;
+    env->local_f32_count = 0;
+    env->local_f64_count = 0;
+    env->SumLocals();
+  }
+
+  BitVector* Analyze(const byte* start, const byte* end) {
+    return AnalyzeLoopAssignmentForTesting(zone(), &env, start, end);
+  }
+};
+
+
+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++) {
+    BitVector* assigned = Analyze(code, code + arraysize(code));
+    for (int j = 0; j < assigned->length(); j++) {
+      CHECK_EQ(false, assigned->Contains(j));
+    }
+    env.AddLocals(kAstI32, 1);
+  }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, One) {
+  env.AddLocals(kAstI32, 5);
+  for (int i = 0; i < 5; i++) {
+    byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i))};
+    BitVector* assigned = Analyze(code, code + arraysize(code));
+    for (int j = 0; j < assigned->length(); j++) {
+      CHECK_EQ(j == i, assigned->Contains(j));
+    }
+  }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) {
+  env.AddLocals(kAstI32, 5);
+  for (int i = 0; i < 5; i++) {
+    byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i)), WASM_SET_ZERO(1)};
+    BitVector* assigned = Analyze(code, code + arraysize(code));
+    for (int j = 0; j < assigned->length(); j++) {
+      CHECK_EQ(j == i, assigned->Contains(j));
+    }
+  }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Two) {
+  env.AddLocals(kAstI32, 5);
+  for (int i = 0; i < 5; i++) {
+    for (int j = 0; j < 5; j++) {
+      byte code[] = {WASM_LOOP(2, WASM_SET_ZERO(i), WASM_SET_ZERO(j))};
+      BitVector* assigned = Analyze(code, code + arraysize(code));
+      for (int k = 0; k < assigned->length(); k++) {
+        bool expected = k == i || k == j;
+        CHECK_EQ(expected, assigned->Contains(k));
+      }
+    }
+  }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, NestedIf) {
+  env.AddLocals(kAstI32, 5);
+  for (int i = 0; i < 5; i++) {
+    byte code[] = {WASM_LOOP(
+        1, WASM_IF_ELSE(WASM_SET_ZERO(0), WASM_SET_ZERO(i), WASM_SET_ZERO(1)))};
+    BitVector* assigned = Analyze(code, code + arraysize(code));
+    for (int j = 0; j < assigned->length(); j++) {
+      bool expected = i == j || j == 0 || j == 1;
+      CHECK_EQ(expected, assigned->Contains(j));
+    }
+  }
+}
+
+
+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) {
+  env.AddLocals(kAstI32, 65000);
+  for (int i = 13; i < 65000; i = static_cast<int>(i * 1.5)) {
+    byte code[] = {kExprLoop,
+                   1,
+                   kExprSetLocal,
+                   LEBByte(i, 0),
+                   LEBByte(i, 1),
+                   LEBByte(i, 2),
+                   11,
+                   12,
+                   13};
+
+    BitVector* assigned = Analyze(code, code + arraysize(code));
+    for (int j = 0; j < assigned->length(); j++) {
+      bool expected = i == j;
+      CHECK_EQ(expected, assigned->Contains(j));
+    }
+  }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Break) {
+  env.AddLocals(kAstI32, 3);
+  byte code[] = {
+      WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_SET_ZERO(1)))),
+      WASM_SET_ZERO(0)};
+
+  BitVector* assigned = Analyze(code, code + arraysize(code));
+  for (int j = 0; j < assigned->length(); j++) {
+    bool expected = j == 1;
+    CHECK_EQ(expected, assigned->Contains(j));
+  }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) {
+  env.AddLocals(kAstI32, 5);
+  byte code[] = {
+      WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0),
+                           WASM_BRV(0, WASM_SET_LOCAL(
+                                           3, WASM_I32_SUB(WASM_GET_LOCAL(0),
+                                                           WASM_I8(1)))))),
+      WASM_GET_LOCAL(0)};
+
+  BitVector* assigned = Analyze(code, code + arraysize(code));
+  for (int j = 0; j < assigned->length(); j++) {
+    bool expected = j == 3;
+    CHECK_EQ(expected, assigned->Contains(j));
+  }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
+  env.AddLocals(kAstI32, 3);
+  const byte kIter = 0;
+  env.AddLocals(kAstF32, 3);
+  const byte kSum = 3;
+
+  byte code[] = {WASM_BLOCK(
+      3,
+      WASM_WHILE(
+          WASM_GET_LOCAL(kIter),
+          WASM_BLOCK(2, WASM_SET_LOCAL(
+                            kSum, WASM_F32_ADD(
+                                      WASM_GET_LOCAL(kSum),
+                                      WASM_LOAD_MEM(MachineType::Float32(),
+                                                    WASM_GET_LOCAL(kIter)))),
+                     WASM_SET_LOCAL(kIter, WASM_I32_SUB(WASM_GET_LOCAL(kIter),
+                                                        WASM_I8(4))))),
+      WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_GET_LOCAL(kSum)),
+      WASM_GET_LOCAL(kIter))};
+
+  BitVector* assigned = Analyze(code + 2, code + arraysize(code));
+  for (int j = 0; j < assigned->length(); j++) {
+    bool expected = j == kIter || j == kSum;
+    CHECK_EQ(expected, assigned->Contains(j));
+  }
+}
+
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/wasm/module-decoder-unittest.cc b/test/unittests/wasm/module-decoder-unittest.cc
index 0738b59..467ffcc 100644
--- a/test/unittests/wasm/module-decoder-unittest.cc
+++ b/test/unittests/wasm/module-decoder-unittest.cc
@@ -45,6 +45,15 @@
                    {kLocalF64, kAstF64}};
 
 
+// TODO(titzer): use these macros everywhere below.
+#define U32_LE(v)                                    \
+  static_cast<byte>(v), static_cast<byte>((v) >> 8), \
+      static_cast<byte>((v) >> 16), static_cast<byte>((v) >> 24)
+
+
+#define U16_LE(v) static_cast<byte>(v), static_cast<byte>((v) >> 8)
+
+
 TEST_F(WasmModuleVerifyTest, DecodeEmpty) {
   static const byte data[1]{kDeclEnd};
   {
@@ -61,7 +70,7 @@
 
 
 TEST_F(WasmModuleVerifyTest, OneGlobal) {
-  const byte data[] = {
+  static const byte data[] = {
       kDeclGlobals,
       1,
       0,
@@ -100,7 +109,7 @@
 
 
 TEST_F(WasmModuleVerifyTest, ZeroGlobals) {
-  const byte data[] = {
+  static const byte data[] = {
       kDeclGlobals, 0,  // declare 0 globals
   };
   ModuleResult result = DecodeModule(data, data + arraysize(data));
@@ -125,7 +134,7 @@
 
 
 TEST_F(WasmModuleVerifyTest, NGlobals) {
-  const byte data[] = {
+  static const byte data[] = {
       0,       0, 0, 0,  // name offset
       kMemI32,           // memory type
       0,                 // exported
@@ -146,7 +155,7 @@
 
 
 TEST_F(WasmModuleVerifyTest, GlobalWithInvalidNameOffset) {
-  const byte data[] = {
+  static const byte data[] = {
       kDeclGlobals,
       1,  // declare one global
       0,
@@ -162,7 +171,7 @@
 
 
 TEST_F(WasmModuleVerifyTest, GlobalWithInvalidMemoryType) {
-  const byte data[] = {
+  static const byte data[] = {
       kDeclGlobals,
       1,  // declare one global
       0,
@@ -178,7 +187,7 @@
 
 
 TEST_F(WasmModuleVerifyTest, TwoGlobals) {
-  const byte data[] = {
+  static const byte data[] = {
       kDeclGlobals,
       2,
       0,
@@ -333,10 +342,10 @@
     EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
     EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
 
-    EXPECT_EQ(523, function->local_int32_count);
-    EXPECT_EQ(1037, function->local_int64_count);
-    EXPECT_EQ(1551, function->local_float32_count);
-    EXPECT_EQ(2065, function->local_float64_count);
+    EXPECT_EQ(523, function->local_i32_count);
+    EXPECT_EQ(1037, function->local_i64_count);
+    EXPECT_EQ(1551, function->local_f32_count);
+    EXPECT_EQ(2065, function->local_f64_count);
 
     EXPECT_TRUE(function->exported);
     EXPECT_FALSE(function->external);
@@ -373,10 +382,10 @@
   EXPECT_EQ(0, function->code_start_offset);
   EXPECT_EQ(0, function->code_end_offset);
 
-  EXPECT_EQ(0, function->local_int32_count);
-  EXPECT_EQ(0, function->local_int64_count);
-  EXPECT_EQ(0, function->local_float32_count);
-  EXPECT_EQ(0, function->local_float64_count);
+  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);
@@ -410,10 +419,10 @@
   EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
   EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
 
-  EXPECT_EQ(0, function->local_int32_count);
-  EXPECT_EQ(0, function->local_int64_count);
-  EXPECT_EQ(0, function->local_float32_count);
-  EXPECT_EQ(0, function->local_float64_count);
+  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);
@@ -450,10 +459,10 @@
   EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
   EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
 
-  EXPECT_EQ(513, function->local_int32_count);
-  EXPECT_EQ(1027, function->local_int64_count);
-  EXPECT_EQ(1541, function->local_float32_count);
-  EXPECT_EQ(2055, function->local_float64_count);
+  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);
@@ -463,10 +472,13 @@
 
 
 TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
-  static const byte kCodeStartOffset = 2 + kDeclGlobalSize + 4 + 2 + 17;
+  static const byte kDeclMemorySize = 4;
+  static const byte kCodeStartOffset =
+      2 + kDeclMemorySize + kDeclGlobalSize + 4 + 2 + 17;
   static const byte kCodeEndOffset = kCodeStartOffset + 3;
 
   static const byte data[] = {
+      kDeclMemory, 28, 28, 1,
       // global#0 --------------------------------------------------
       kDeclGlobals, 1, 0, 0, 0, 0,  // name offset
       kMemU8,                       // memory type
@@ -531,24 +543,17 @@
 
 TEST_F(WasmModuleVerifyTest, OneDataSegment) {
   const byte data[] = {
-      kDeclDataSegments,
-      1,
-      0xaa,
-      0xbb,
-      0x09,
+      kDeclMemory, 28, 28, 1, kDeclDataSegments, 1, 0xaa, 0xbb, 0x09,
       0,  // dest addr
-      11,
-      0,
-      0,
+      11,          0,  0,
       0,  // source offset
-      3,
-      0,
-      0,
+      3,           0,  0,
       0,  // source size
       1,  // init
   };
 
   {
+    EXPECT_VERIFIES(data);
     ModuleResult result = DecodeModule(data, data + arraysize(data));
     EXPECT_TRUE(result.ok());
     EXPECT_EQ(0, result.val->globals->size());
@@ -565,7 +570,7 @@
     if (result.val) delete result.val;
   }
 
-  for (size_t size = 1; size < arraysize(data); size++) {
+  for (size_t size = 5; size < arraysize(data); size++) {
     // Should fall off end of module bytes.
     ModuleResult result = DecodeModule(data, data + size);
     EXPECT_FALSE(result.ok());
@@ -576,32 +581,18 @@
 
 TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
   const byte data[] = {
-      kDeclDataSegments,
-      2,
-      0xee,
-      0xff,
-      0x07,
+      kDeclMemory, 28,   28,   1, kDeclDataSegments, 2, 0xee, 0xff, 0x07,
       0,  // dest addr
-      9,
-      0,
-      0,
+      9,           0,    0,
       0,  // #0: source offset
-      4,
-      0,
-      0,
+      4,           0,    0,
       0,  // source size
       0,  // init
-      0xcc,
-      0xdd,
-      0x06,
+      0xcc,        0xdd, 0x06,
       0,  // #1: dest addr
-      6,
-      0,
-      0,
+      6,           0,    0,
       0,  // source offset
-      10,
-      0,
-      0,
+      10,          0,    0,
       0,  // source size
       1,  // init
   };
@@ -629,7 +620,7 @@
     if (result.val) delete result.val;
   }
 
-  for (size_t size = 1; size < arraysize(data); size++) {
+  for (size_t size = 5; size < arraysize(data); size++) {
     // Should fall off end of module bytes.
     ModuleResult result = DecodeModule(data, data + size);
     EXPECT_FALSE(result.ok());
@@ -638,6 +629,71 @@
 }
 
 
+TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidSource) {
+  const int dest_addr = 0x100;
+  const byte mem_size_log2 = 15;
+  const int kDataSize = 19;
+
+  for (int source_offset = 0; source_offset < 5 + kDataSize; source_offset++) {
+    for (int source_size = -1; source_size < 5 + kDataSize; source_size += 3) {
+      byte data[] = {
+          kDeclMemory,
+          mem_size_log2,
+          mem_size_log2,
+          1,
+          kDeclDataSegments,
+          1,
+          U32_LE(dest_addr),
+          U32_LE(source_offset),
+          U32_LE(source_size),
+          1,  // init
+      };
+
+      STATIC_ASSERT(kDataSize == arraysize(data));
+
+      if (source_offset < kDataSize && source_size >= 0 &&
+          (source_offset + source_size) <= kDataSize) {
+        EXPECT_VERIFIES(data);
+      } else {
+        EXPECT_FAILURE(data);
+      }
+    }
+  }
+}
+
+
+TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidDest) {
+  const int source_size = 3;
+  const int source_offset = 11;
+
+  for (byte mem_size_log2 = 12; mem_size_log2 < 20; mem_size_log2++) {
+    int mem_size = 1 << mem_size_log2;
+
+    for (int dest_addr = mem_size - source_size;
+         dest_addr < mem_size + source_size; dest_addr++) {
+      byte data[] = {
+          kDeclMemory,
+          mem_size_log2,
+          mem_size_log2,
+          1,
+          kDeclDataSegments,
+          1,
+          U32_LE(dest_addr),
+          U32_LE(source_offset),
+          U32_LE(source_size),
+          1,  // init
+      };
+
+      if (dest_addr <= (mem_size - source_size)) {
+        EXPECT_VERIFIES(data);
+      } else {
+        EXPECT_FAILURE(data);
+      }
+    }
+  }
+}
+
+
 // To make below tests for indirect calls much shorter.
 #define FUNCTION(sig_index, external)                \
   kDeclFunctionImport, static_cast<byte>(sig_index), \
@@ -848,7 +904,7 @@
 
 
 TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
-  byte data[] = {
+  static const byte data[] = {
       0,       kLocalVoid,  // signature
       3,       0,           // local int32 count
       4,       0,           // local int64 count
@@ -868,10 +924,10 @@
     EXPECT_EQ(0, function->name_offset);
     EXPECT_EQ(arraysize(data) - 1, function->code_start_offset);
     EXPECT_EQ(arraysize(data), function->code_end_offset);
-    EXPECT_EQ(3, function->local_int32_count);
-    EXPECT_EQ(4, function->local_int64_count);
-    EXPECT_EQ(5, function->local_float32_count);
-    EXPECT_EQ(6, function->local_float64_count);
+    EXPECT_EQ(3, function->local_i32_count);
+    EXPECT_EQ(4, function->local_i64_count);
+    EXPECT_EQ(5, function->local_f32_count);
+    EXPECT_EQ(6, function->local_f64_count);
     EXPECT_FALSE(function->external);
     EXPECT_FALSE(function->exported);
   }
@@ -889,7 +945,7 @@
 
 
 TEST_F(WasmModuleVerifyTest, WLLSectionEmpty) {
-  const byte data[] = {
+  static const byte data[] = {
       kDeclWLL, 0,  // empty section
   };
   ModuleResult result = DecodeModule(data, data + arraysize(data));
@@ -899,7 +955,7 @@
 
 
 TEST_F(WasmModuleVerifyTest, WLLSectionOne) {
-  const byte data[] = {
+  static const byte data[] = {
       kDeclWLL,
       1,  // LEB128 1
       0,  // one byte section
@@ -911,10 +967,10 @@
 
 
 TEST_F(WasmModuleVerifyTest, WLLSectionTen) {
-  const byte data[] = {
+  static const byte data[] = {
       kDeclWLL,
-      10,                             // LEB128 10
-      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,  // 10 byte section
+      10,                                    // LEB128 10
+      1,        2, 3, 4, 5, 6, 7, 8, 9, 10,  // 10 byte section
   };
   ModuleResult result = DecodeModule(data, data + arraysize(data));
   EXPECT_TRUE(result.ok());
@@ -923,20 +979,19 @@
 
 
 TEST_F(WasmModuleVerifyTest, WLLSectionOverflow) {
-  const byte data[] = {
+  static const byte data[] = {
       kDeclWLL,
-      11,                             // LEB128 11
-      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,  // 10 byte section
+      11,                                    // LEB128 11
+      1,        2, 3, 4, 5, 6, 7, 8, 9, 10,  // 10 byte section
   };
   EXPECT_FAILURE(data);
 }
 
 
 TEST_F(WasmModuleVerifyTest, WLLSectionUnderflow) {
-  const byte data[] = {
-    kDeclWLL,
-    0xff, 0xff, 0xff, 0xff, 0x0f,  // LEB128 0xffffffff
-    1, 2, 3, 4,                    // 4 byte section
+  static const byte data[] = {
+      kDeclWLL, 0xff, 0xff, 0xff, 0xff, 0x0f,  // LEB128 0xffffffff
+      1,        2,    3,    4,                 // 4 byte section
   };
   EXPECT_FAILURE(data);
 }
@@ -944,14 +999,92 @@
 
 TEST_F(WasmModuleVerifyTest, WLLSectionLoop) {
   // Would infinite loop decoding if wrapping and allowed.
-  const byte data[] = {
-    kDeclWLL,
-    0xfa, 0xff, 0xff, 0xff, 0x0f,  // LEB128 0xfffffffa
-    1, 2, 3, 4,                    // 4 byte section
+  static const byte data[] = {
+      kDeclWLL, 0xfa, 0xff, 0xff, 0xff, 0x0f,  // LEB128 0xfffffffa
+      1,        2,    3,    4,                 // 4 byte section
   };
   EXPECT_FAILURE(data);
 }
 
+TEST_F(WasmModuleVerifyTest, ImportTable_empty) {
+  static const byte data[] = {kDeclSignatures, 0, kDeclImportTable, 0};
+  EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_nosigs) {
+  static const byte data[] = {kDeclImportTable, 0};
+  EXPECT_FAILURE(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) {
+  static const byte data[] = {
+      kDeclSignatures,
+      0,
+      kDeclImportTable,
+      1,
+      0,
+      0,  // sig index
+      1,
+      0,
+      0,
+      0,  // module name
+      1,
+      0,
+      0,
+      0  // function name
+  };
+  EXPECT_FAILURE(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
+  static const byte data[] = {
+      kDeclSignatures,
+      1,
+      0,
+      static_cast<byte>(kAstStmt),
+      kDeclImportTable,
+      1,
+      0,
+      0,  // sig index
+      1,
+      0,
+      0,
+      0,  // module name
+      1,
+      0,
+      0,
+      0  // function name
+  };
+  EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
+  static const byte data[] = {
+      kDeclSignatures,
+      1,
+      0,
+      static_cast<byte>(kAstStmt),
+      kDeclImportTable,
+      1,
+      0,
+      0,  // sig index
+      1,
+      0,
+      0,
+      0,  // module name
+      1,
+      0,
+      0,
+      0  // function name
+  };
+
+  for (size_t length = 5; length < sizeof(data); length++) {
+    ModuleResult result = DecodeModule(data, data + length);
+    EXPECT_FALSE(result.ok());
+    if (result.val) delete result.val;
+  }
+}
+
 }  // 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 c5bb5ec..f3f604b 100644
--- a/test/unittests/wasm/wasm-macro-gen-unittest.cc
+++ b/test/unittests/wasm/wasm-macro-gen-unittest.cc
@@ -131,15 +131,25 @@
   EXPECT_SIZE(6, WASM_LOOP(3, WASM_NOP, WASM_NOP, WASM_ZERO));
 }
 
-
-TEST_F(WasmMacroGenTest, FunctionCalls) {
+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(4, WASM_CALL_FUNCTION(0, WASM_ZERO));
   EXPECT_SIZE(6, WASM_CALL_FUNCTION(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(4, WASM_CALL_IMPORT(0, WASM_ZERO));
+  EXPECT_SIZE(6, WASM_CALL_IMPORT(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));
diff --git a/test/webkit/function-declarations-in-switch-statement-expected.txt b/test/webkit/function-declarations-in-switch-statement-expected.txt
index 602b8b9..938e028 100644
--- a/test/webkit/function-declarations-in-switch-statement-expected.txt
+++ b/test/webkit/function-declarations-in-switch-statement-expected.txt
@@ -26,7 +26,7 @@
 WARN: shouldBe() expects string arguments
 PASS 20 is 20
 WARN: shouldBe() expects string arguments
-PASS 20 is 20
+FAIL -1 should be 20. Was -1.
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/test/webkit/webkit.status b/test/webkit/webkit.status
index 971cf46..fa52742 100644
--- a/test/webkit/webkit.status
+++ b/test/webkit/webkit.status
@@ -35,9 +35,8 @@
   'dfg-inline-arguments-reset-changetype': [PASS, FAIL],
   # TODO(turbofan): We run out of stack earlier on 64-bit for now.
   'fast/js/deep-recursion-test': [PASS, NO_VARIANTS],
-  # This test leads to a SyntaxError from conflicting let declarations
-  # in ES2015
-  'function-declarations-in-switch-statement': [FAIL],
+  # Irregexp interpreter overflows stack. We should just not crash.
+  'fast/js/regexp-stack-overflow': [PASS, FAIL],
 }],  # ALWAYS
 ['mode == debug', {
   # Too slow in debug mode.