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/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);