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/es6/array-concat.js b/test/mjsunit/es6/array-concat.js
new file mode 100644
index 0000000..bc9e1a0
--- /dev/null
+++ b/test/mjsunit/es6/array-concat.js
@@ -0,0 +1,866 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-proxies --harmony-reflect
+
+(function testArrayConcatArity() {
+  "use strict";
+  assertEquals(1, Array.prototype.concat.length);
+})();
+
+
+(function testArrayConcatNoPrototype() {
+  "use strict";
+  assertEquals(void 0, Array.prototype.concat.prototype);
+})();
+
+
+(function testArrayConcatDescriptor() {
+  "use strict";
+  var desc = Object.getOwnPropertyDescriptor(Array.prototype, 'concat');
+  assertEquals(false, desc.enumerable);
+})();
+
+
+(function testConcatArrayLike() {
+  "use strict";
+  var obj = {
+    "length": 6,
+    "1": "A",
+    "3": "B",
+    "5": "C"
+  };
+  obj[Symbol.isConcatSpreadable] = true;
+  var obj2 = { length: 3, "0": "0", "1": "1", "2": "2" };
+  var arr = ["X", "Y", "Z"];
+  assertEquals([void 0, "A", void 0, "B", void 0, "C",
+               { "length": 3, "0": "0", "1": "1", "2": "2" },
+               "X", "Y", "Z"], Array.prototype.concat.call(obj, obj2, arr));
+})();
+
+
+(function testConcatArrayLikeStringLength() {
+  "use strict";
+  var obj = {
+    "length": "6",
+    "1": "A",
+    "3": "B",
+    "5": "C"
+  };
+  obj[Symbol.isConcatSpreadable] = true;
+  var obj2 = { length: 3, "0": "0", "1": "1", "2": "2" };
+  var arr = ["X", "Y", "Z"];
+  assertEquals([void 0, "A", void 0, "B", void 0, "C",
+               { "length": 3, "0": "0", "1": "1", "2": "2" },
+               "X", "Y", "Z"], Array.prototype.concat.call(obj, obj2, arr));
+})();
+
+
+(function testConcatArrayLikeNegativeLength() {
+  "use strict";
+  var obj = {
+    "length": -6,
+    "1": "A",
+    "3": "B",
+    "5": "C"
+  };
+  obj[Symbol.isConcatSpreadable] = true;
+  assertEquals([], [].concat(obj));
+  obj.length = -6.7;
+  assertEquals([], [].concat(obj));
+  obj.length = "-6";
+  assertEquals([], [].concat(obj));
+})();
+
+
+(function testConcatArrayLikeToLengthThrows() {
+  "use strict";
+  var obj = {
+    "length": {valueOf: null, toString: null},
+    "1": "A",
+    "3": "B",
+    "5": "C"
+  };
+  obj[Symbol.isConcatSpreadable] = true;
+  var obj2 = { length: 3, "0": "0", "1": "1", "2": "2" };
+  var arr = ["X", "Y", "Z"];
+  assertThrows(function() {
+    Array.prototype.concat.call(obj, obj2, arr);
+  }, TypeError);
+})();
+
+
+(function testConcatArrayLikePrimitiveNonNumberLength() {
+  "use strict";
+  var obj = {
+    "1": "A",
+    "3": "B",
+    "5": "C"
+  };
+  obj[Symbol.isConcatSpreadable] = true;
+  obj.length = {toString: function() { return "SIX"; }, valueOf: null };
+  assertEquals([], [].concat(obj));
+  obj.length = {toString: null, valueOf: function() { return "SIX"; } };
+  assertEquals([], [].concat(obj));
+})();
+
+
+(function testConcatArrayLikeLengthToStringThrows() {
+  "use strict";
+  function MyError() {}
+  var obj = {
+    "length": { toString: function() {
+        throw new MyError();
+      }, valueOf: null
+    },
+    "1": "A",
+    "3": "B",
+    "5": "C"
+  };
+  obj[Symbol.isConcatSpreadable] = true;
+  assertThrows(function() {
+    [].concat(obj);
+  }, MyError);
+})();
+
+
+(function testConcatArrayLikeLengthValueOfThrows() {
+  "use strict";
+  function MyError() {}
+  var obj = {
+    "length": { valueOf: function() {
+      throw new MyError();
+    }, toString: null
+  },
+  "1": "A",
+  "3": "B",
+  "5": "C"
+};
+obj[Symbol.isConcatSpreadable] = true;
+assertThrows(function() {
+  [].concat(obj);
+}, MyError);
+})();
+
+
+(function testConcatHoleyArray() {
+  "use strict";
+  var arr = [];
+  arr[4] = "Item 4";
+  arr[8] = "Item 8";
+  var arr2 = [".", "!", "?"];
+  assertEquals([void 0, void 0, void 0, void 0, "Item 4", void 0, void 0,
+                void 0, "Item 8", ".", "!", "?"], arr.concat(arr2));
+})();
+
+
+(function testIsConcatSpreadableGetterThrows() {
+  "use strict";
+  function MyError() {}
+  var obj = {};
+  Object.defineProperty(obj, Symbol.isConcatSpreadable, {
+    get: function() { throw new MyError(); }
+  });
+
+  assertThrows(function() {
+    [].concat(obj);
+  }, MyError);
+
+  assertThrows(function() {
+    Array.prototype.concat.call(obj, 1, 2, 3);
+  }, MyError);
+})();
+
+
+(function testConcatLengthThrows() {
+  "use strict";
+  function MyError() {}
+  var obj = {};
+  obj[Symbol.isConcatSpreadable] = true;
+  Object.defineProperty(obj, "length", {
+    get: function() { throw new MyError(); }
+  });
+
+  assertThrows(function() {
+    [].concat(obj);
+  }, MyError);
+
+  assertThrows(function() {
+    Array.prototype.concat.call(obj, 1, 2, 3);
+  }, MyError);
+})();
+
+
+(function testConcatArraySubclass() {
+  "use strict";
+  // If @@isConcatSpreadable is not used, the value of IsArray(O)
+  // is used to determine the spreadable property.
+  class A extends Array {}
+  var obj = [].concat(new A(1, 2, 3), new A(4, 5, 6), new A(7, 8, 9));
+  assertEquals(9, obj.length);
+  for (var i = 0; i < obj.length; ++i) {
+    assertEquals(i + 1, obj[i]);
+  }
+
+  // TODO(caitp): when concat is called on instances of classes which extend
+  // Array, they should:
+  //
+  // - return an instance of the class, rather than an Array instance (if from
+  //   same Realm)
+  // - always treat such classes as concat-spreadable
+})();
+
+
+(function testConcatArraySubclassOptOut() {
+  "use strict";
+  class A extends Array {
+    get [Symbol.isConcatSpreadable]() { return false; }
+  }
+  var obj = [].concat(new A(1, 2, 3), new A(4, 5, 6), new A(7, 8, 9));
+  assertEquals(3, obj.length);
+  assertEquals(3, obj[0].length);
+  assertEquals(3, obj[1].length);
+  assertEquals(3, obj[2].length);
+})();
+
+
+(function testConcatNonArray() {
+  "use strict";
+  class NonArray {
+    constructor() { Array.apply(this, arguments); }
+  };
+
+  var obj = new NonArray(1,2,3);
+  var result = Array.prototype.concat.call(obj, 4, 5, 6);
+  assertEquals(Array, result.constructor);
+  assertEquals([obj,4,5,6], result);
+  assertFalse(result instanceof NonArray);
+})();
+
+
+function testConcatTypedArray(type, elems, modulo) {
+  "use strict";
+  var items = new Array(elems);
+  var ta_by_len = new type(elems);
+  for (var i = 0; i < elems; ++i) {
+    ta_by_len[i] = items[i] = modulo === false ? i : elems % modulo;
+  }
+  var ta = new type(items);
+  assertEquals([ta, ta], [].concat(ta, ta));
+  ta[Symbol.isConcatSpreadable] = true;
+  assertEquals(items, [].concat(ta));
+
+  assertEquals([ta_by_len, ta_by_len], [].concat(ta_by_len, ta_by_len));
+  ta_by_len[Symbol.isConcatSpreadable] = true;
+  assertEquals(items, [].concat(ta_by_len));
+
+  // TypedArray with fake `length`.
+  ta = new type(1);
+  var defValue = ta[0];
+  var expected = new Array(4000);
+  expected[0] = defValue;
+
+  Object.defineProperty(ta, "length", { value: 4000 });
+  ta[Symbol.isConcatSpreadable] = true;
+  assertEquals(expected, [].concat(ta));
+}
+
+(function testConcatSmallTypedArray() {
+  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 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);
+})();
+
+
+(function testConcatStrictArguments() {
+  var args = (function(a, b, c) { "use strict"; return arguments; })(1,2,3);
+  args[Symbol.isConcatSpreadable] = true;
+  assertEquals([1, 2, 3, 1, 2, 3], [].concat(args, args));
+
+  Object.defineProperty(args, "length", { value: 6 });
+  assertEquals([1, 2, 3, void 0, void 0, void 0], [].concat(args));
+})();
+
+
+(function testConcatSloppyArguments() {
+  var args = (function(a, b, c) { return arguments; })(1,2,3);
+  args[Symbol.isConcatSpreadable] = true;
+  assertEquals([1, 2, 3, 1, 2, 3], [].concat(args, args));
+
+  Object.defineProperty(args, "length", { value: 6 });
+  assertEquals([1, 2, 3, void 0, void 0, void 0], [].concat(args));
+})();
+
+
+(function testConcatSloppyArgumentsWithDupes() {
+  var args = (function(a, a, a) { return arguments; })(1,2,3);
+  args[Symbol.isConcatSpreadable] = true;
+  assertEquals([1, 2, 3, 1, 2, 3], [].concat(args, args));
+
+  Object.defineProperty(args, "length", { value: 6 });
+  assertEquals([1, 2, 3, void 0, void 0, void 0], [].concat(args));
+})();
+
+
+(function testConcatSloppyArgumentsThrows() {
+  function MyError() {}
+  var args = (function(a) { return arguments; })(1,2,3);
+  Object.defineProperty(args, 0, {
+    get: function() { throw new MyError(); }
+  });
+  args[Symbol.isConcatSpreadable] = true;
+  assertThrows(function() {
+    return [].concat(args, args);
+  }, MyError);
+})();
+
+
+(function testConcatHoleySloppyArguments() {
+  var args = (function(a) { return arguments; })(1,2,3);
+  delete args[1];
+  args[Symbol.isConcatSpreadable] = true;
+  assertEquals([1, void 0, 3, 1, void 0, 3], [].concat(args, args));
+})();
+
+
+(function testConcatSpreadableStringWrapper() {
+  "use strict";
+  var str1 = new String("yuck\uD83D\uDCA9")
+  // String wrapper objects are not concat-spreadable by default
+  assertEquals([str1], [].concat(str1));
+
+  // String wrapper objects may be individually concat-spreadable
+  str1[Symbol.isConcatSpreadable] = true;
+  assertEquals(["y", "u", "c", "k", "\uD83D", "\uDCA9"],
+               [].concat(str1));
+
+  String.prototype[Symbol.isConcatSpreadable] = true;
+  // String wrapper objects may be concat-spreadable
+  assertEquals(["y", "u", "c", "k", "\uD83D", "\uDCA9"],
+               [].concat(new String("yuck\uD83D\uDCA9")));
+
+  // String values are never concat-spreadable
+  assertEquals(["yuck\uD83D\uDCA9"], [].concat("yuck\uD83D\uDCA9"));
+  delete String.prototype[Symbol.isConcatSpreadable];
+})();
+
+
+(function testConcatSpreadableBooleanWrapper() {
+  "use strict";
+  var bool = new Boolean(true)
+  // Boolean wrapper objects are not concat-spreadable by default
+  assertEquals([bool], [].concat(bool));
+
+  // Boolean wrapper objects may be individually concat-spreadable
+  bool[Symbol.isConcatSpreadable] = true;
+  bool.length = 3;
+  bool[0] = 1, bool[1] = 2, bool[2] = 3;
+  assertEquals([1, 2, 3], [].concat(bool));
+
+  Boolean.prototype[Symbol.isConcatSpreadable] = true;
+  // Boolean wrapper objects may be concat-spreadable
+  assertEquals([], [].concat(new Boolean(true)));
+  Boolean.prototype[0] = 1;
+  Boolean.prototype[1] = 2;
+  Boolean.prototype[2] = 3;
+  Boolean.prototype.length = 3;
+  assertEquals([1,2,3], [].concat(new Boolean(true)));
+
+  // Boolean values are never concat-spreadable
+  assertEquals([true], [].concat(true));
+  delete Boolean.prototype[Symbol.isConcatSpreadable];
+  delete Boolean.prototype[0];
+  delete Boolean.prototype[1];
+  delete Boolean.prototype[2];
+  delete Boolean.prototype.length;
+})();
+
+
+(function testConcatSpreadableNumberWrapper() {
+  "use strict";
+  var num = new Number(true)
+  // Number wrapper objects are not concat-spreadable by default
+  assertEquals([num], [].concat(num));
+
+  // Number wrapper objects may be individually concat-spreadable
+  num[Symbol.isConcatSpreadable] = true;
+  num.length = 3;
+  num[0] = 1, num[1] = 2, num[2] = 3;
+  assertEquals([1, 2, 3], [].concat(num));
+
+  Number.prototype[Symbol.isConcatSpreadable] = true;
+  // Number wrapper objects may be concat-spreadable
+  assertEquals([], [].concat(new Number(123)));
+  Number.prototype[0] = 1;
+  Number.prototype[1] = 2;
+  Number.prototype[2] = 3;
+  Number.prototype.length = 3;
+  assertEquals([1,2,3], [].concat(new Number(123)));
+
+  // Number values are never concat-spreadable
+  assertEquals([true], [].concat(true));
+  delete Number.prototype[Symbol.isConcatSpreadable];
+  delete Number.prototype[0];
+  delete Number.prototype[1];
+  delete Number.prototype[2];
+  delete Number.prototype.length;
+})();
+
+
+(function testConcatSpreadableFunction() {
+  "use strict";
+  var fn = function(a, b, c) {}
+  // Functions are not concat-spreadable by default
+  assertEquals([fn], [].concat(fn));
+
+  // Functions may be individually concat-spreadable
+  fn[Symbol.isConcatSpreadable] = true;
+  fn[0] = 1, fn[1] = 2, fn[2] = 3;
+  assertEquals([1, 2, 3], [].concat(fn));
+
+  Function.prototype[Symbol.isConcatSpreadable] = true;
+  // Functions may be concat-spreadable
+  assertEquals([void 0, void 0, void 0], [].concat(function(a,b,c) {}));
+  Function.prototype[0] = 1;
+  Function.prototype[1] = 2;
+  Function.prototype[2] = 3;
+  assertEquals([1,2,3], [].concat(function(a, b, c) {}));
+
+  delete Function.prototype[Symbol.isConcatSpreadable];
+  delete Function.prototype[0];
+  delete Function.prototype[1];
+  delete Function.prototype[2];
+})();
+
+
+(function testConcatSpreadableRegExp() {
+  "use strict";
+  var re = /abc/;
+  // RegExps are not concat-spreadable by default
+  assertEquals([re], [].concat(re));
+
+  // RegExps may be individually concat-spreadable
+  re[Symbol.isConcatSpreadable] = true;
+  re[0] = 1, re[1] = 2, re[2] = 3, re.length = 3;
+  assertEquals([1, 2, 3], [].concat(re));
+
+  // RegExps may be concat-spreadable
+  RegExp.prototype[Symbol.isConcatSpreadable] = true;
+  RegExp.prototype.length = 3;
+
+  assertEquals([void 0, void 0, void 0], [].concat(/abc/));
+  RegExp.prototype[0] = 1;
+  RegExp.prototype[1] = 2;
+  RegExp.prototype[2] = 3;
+  assertEquals([1,2,3], [].concat(/abc/));
+
+  delete RegExp.prototype[Symbol.isConcatSpreadable];
+  delete RegExp.prototype[0];
+  delete RegExp.prototype[1];
+  delete RegExp.prototype[2];
+  delete RegExp.prototype.length;
+})();
+
+
+(function testArrayConcatSpreadableSparseObject() {
+  "use strict";
+  var obj = { length: 5 };
+  obj[Symbol.isConcatSpreadable] = true;
+  assertEquals([void 0, void 0, void 0, void 0, void 0], [].concat(obj));
+
+  obj.length = 4000;
+  assertEquals(new Array(4000), [].concat(obj));
+})();
+
+
+// ES5 tests
+(function testArrayConcatES5() {
+  "use strict";
+  var poses;
+  var pos;
+
+  poses = [140, 4000000000];
+  while (pos = poses.shift()) {
+    var a = new Array(pos);
+    var array_proto = [];
+    a.__proto__ = array_proto;
+    assertEquals(pos, a.length);
+    a.push('foo');
+    assertEquals(pos + 1, a.length);
+    var b = ['bar'];
+    var c = a.concat(b);
+    assertEquals(pos + 2, c.length);
+    assertEquals("undefined", typeof(c[pos - 1]));
+    assertEquals("foo", c[pos]);
+    assertEquals("bar", c[pos + 1]);
+
+    // Can we fool the system by putting a number in a string?
+    var onetwofour = "124";
+    a[onetwofour] = 'doo';
+    assertEquals(a[124], 'doo');
+    c = a.concat(b);
+    assertEquals(c[124], 'doo');
+
+    // If we put a number in the prototype, then the spec says it should be
+    // copied on concat.
+    array_proto["123"] = 'baz';
+    assertEquals(a[123], 'baz');
+
+    c = a.concat(b);
+    assertEquals(pos + 2, c.length);
+    assertEquals("baz", c[123]);
+    assertEquals("undefined", typeof(c[pos - 1]));
+    assertEquals("foo", c[pos]);
+    assertEquals("bar", c[pos + 1]);
+
+    // When we take the number off the prototype it disappears from a, but
+    // the concat put it in c itself.
+    array_proto["123"] = undefined;
+    assertEquals("undefined", typeof(a[123]));
+    assertEquals("baz", c[123]);
+
+    // If the element of prototype is shadowed, the element on the instance
+    // should be copied, but not the one on the prototype.
+    array_proto[123] = 'baz';
+    a[123] = 'xyz';
+    assertEquals('xyz', a[123]);
+    c = a.concat(b);
+    assertEquals('xyz', c[123]);
+
+    // Non-numeric properties on the prototype or the array shouldn't get
+    // copied.
+    array_proto.moe = 'joe';
+    a.ben = 'jerry';
+    assertEquals(a["moe"], 'joe');
+    assertEquals(a["ben"], 'jerry');
+    c = a.concat(b);
+    // ben was not copied
+    assertEquals("undefined", typeof(c.ben));
+
+    // When we take moe off the prototype it disappears from all arrays.
+    array_proto.moe = undefined;
+    assertEquals("undefined", typeof(c.moe));
+
+    // Negative indices don't get concated.
+    a[-1] = 'minus1';
+    assertEquals("minus1", a[-1]);
+    assertEquals("undefined", typeof(a[0xffffffff]));
+    c = a.concat(b);
+    assertEquals("undefined", typeof(c[-1]));
+    assertEquals("undefined", typeof(c[0xffffffff]));
+    assertEquals(c.length, a.length + 1);
+  }
+
+  poses = [140, 4000000000];
+  while (pos = poses.shift()) {
+    var a = new Array(pos);
+    assertEquals(pos, a.length);
+    a.push('foo');
+    assertEquals(pos + 1, a.length);
+    var b = ['bar'];
+    var c = a.concat(b);
+    assertEquals(pos + 2, c.length);
+    assertEquals("undefined", typeof(c[pos - 1]));
+    assertEquals("foo", c[pos]);
+    assertEquals("bar", c[pos + 1]);
+
+    // Can we fool the system by putting a number in a string?
+    var onetwofour = "124";
+    a[onetwofour] = 'doo';
+    assertEquals(a[124], 'doo');
+    c = a.concat(b);
+    assertEquals(c[124], 'doo');
+
+    // If we put a number in the prototype, then the spec says it should be
+    // copied on concat.
+    Array.prototype["123"] = 'baz';
+    assertEquals(a[123], 'baz');
+
+    c = a.concat(b);
+    assertEquals(pos + 2, c.length);
+    assertEquals("baz", c[123]);
+    assertEquals("undefined", typeof(c[pos - 1]));
+    assertEquals("foo", c[pos]);
+    assertEquals("bar", c[pos + 1]);
+
+    // When we take the number off the prototype it disappears from a, but
+    // the concat put it in c itself.
+    Array.prototype["123"] = undefined;
+    assertEquals("undefined", typeof(a[123]));
+    assertEquals("baz", c[123]);
+
+    // If the element of prototype is shadowed, the element on the instance
+    // should be copied, but not the one on the prototype.
+    Array.prototype[123] = 'baz';
+    a[123] = 'xyz';
+    assertEquals('xyz', a[123]);
+    c = a.concat(b);
+    assertEquals('xyz', c[123]);
+
+    // Non-numeric properties on the prototype or the array shouldn't get
+    // copied.
+    Array.prototype.moe = 'joe';
+    a.ben = 'jerry';
+    assertEquals(a["moe"], 'joe');
+    assertEquals(a["ben"], 'jerry');
+    c = a.concat(b);
+    // ben was not copied
+    assertEquals("undefined", typeof(c.ben));
+    // moe was not copied, but we can see it through the prototype
+    assertEquals("joe", c.moe);
+
+    // When we take moe off the prototype it disappears from all arrays.
+    Array.prototype.moe = undefined;
+    assertEquals("undefined", typeof(c.moe));
+
+    // Negative indices don't get concated.
+    a[-1] = 'minus1';
+    assertEquals("minus1", a[-1]);
+    assertEquals("undefined", typeof(a[0xffffffff]));
+    c = a.concat(b);
+    assertEquals("undefined", typeof(c[-1]));
+    assertEquals("undefined", typeof(c[0xffffffff]));
+    assertEquals(c.length, a.length + 1);
+
+  }
+
+  a = [];
+  c = a.concat('Hello');
+  assertEquals(1, c.length);
+  assertEquals("Hello", c[0]);
+  assertEquals("Hello", c.toString());
+
+  // Check that concat preserves holes.
+  var holey = [void 0,'a',,'c'].concat(['d',,'f',[0,,2],void 0])
+  assertEquals(9, holey.length);  // hole in embedded array is ignored
+  for (var i = 0; i < holey.length; i++) {
+    if (i == 2 || i == 5) {
+      assertFalse(i in holey);
+    } else {
+      assertTrue(i in holey);
+    }
+  }
+
+  // Polluted prototype from prior tests.
+  delete Array.prototype[123];
+
+  // Check that concat reads getters in the correct order.
+  var arr1 = [,2];
+  var arr2 = [1,3];
+  var r1 = [].concat(arr1, arr2);  // [,2,1,3]
+  assertEquals([,2,1,3], r1);
+
+  // Make first array change length of second array.
+  Object.defineProperty(arr1, 0, {get: function() {
+        arr2.push("X");
+        return undefined;
+      }, configurable: true})
+  var r2 = [].concat(arr1, arr2);  // [undefined,2,1,3,"X"]
+  assertEquals([undefined,2,1,3,"X"], r2);
+
+  // Make first array change length of second array massively.
+  arr2.length = 2;
+  Object.defineProperty(arr1, 0, {get: function() {
+        arr2[500000] = "X";
+        return undefined;
+      }, configurable: true})
+  var r3 = [].concat(arr1, arr2);  // [undefined,2,1,3,"X"]
+  var expected = [undefined,2,1,3];
+  expected[500000 + 2] = "X";
+
+  assertEquals(expected, r3);
+
+  var arr3 = [];
+  var trace = [];
+  var expectedTrace = []
+  function mkGetter(i) { return function() { trace.push(i); }; }
+  arr3.length = 10000;
+  for (var i = 0; i < 100; i++) {
+    Object.defineProperty(arr3, i * i, {get: mkGetter(i)});
+    expectedTrace[i] = i;
+    expectedTrace[100 + i] = i;
+  }
+  var r4 = [0].concat(arr3, arr3);
+  assertEquals(1 + arr3.length * 2, r4.length);
+  assertEquals(expectedTrace, trace);
+
+  // Clean up.
+  delete Array.prototype[123];
+  delete Array.prototype["123"];
+  delete Array.prototype["moe"];
+})();
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests with proxies
+
+// Note: concat does not currently support species so there is no difference
+// between [].concat(foo) and Array.prototype.concat.apply(foo).
+
+
+var log = [];
+var logger = {};
+var handler = new Proxy({}, logger);
+
+logger.get = function(t, trap, r) {
+  return function(...args) {
+    log.push([trap, ...args]);
+    return Reflect[trap](...args);
+  }
+};
+
+
+(function testUnspreadableNonArrayLikeProxy() {
+  var target = {0: "a", 1: "b"};
+  var obj = new Proxy(target, handler);
+
+  log.length = 0;
+  assertEquals([obj], [].concat(obj));
+  assertEquals(1, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+
+  log.length = 0;
+  assertEquals([obj], Array.prototype.concat.apply(obj));
+  assertEquals(1, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+})();
+
+
+(function testSpreadableNonArrayLikeProxy() {
+  var target = {0: "a", 1: "b", [Symbol.isConcatSpreadable]: "truish"};
+  var obj = new Proxy(target, handler);
+
+  log.length = 0;
+  assertEquals([], [].concat(obj));
+  assertEquals(2, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+  assertEquals(["get", target, "length", obj], log[1]);
+
+  log.length = 0;
+  assertEquals([], Array.prototype.concat.apply(obj));
+  assertEquals(2, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+  assertEquals(["get", target, "length", obj], log[1]);
+
+  target.length = 3;
+
+  log.length = 0;
+  assertEquals(["a", "b", undefined], [].concat(obj));
+  assertEquals(7, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+  assertEquals(["get", target, "length", obj], log[1]);
+  assertEquals(["has", target, "0"], log[2]);
+  assertEquals(["get", target, "0", obj], log[3]);
+  assertEquals(["has", target, "1"], log[4]);
+  assertEquals(["get", target, "1", obj], log[5]);
+  assertEquals(["has", target, "2"], log[6]);
+
+  log.length = 0;
+  assertEquals(["a", "b", undefined], Array.prototype.concat.apply(obj));
+  assertEquals(7, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+  assertEquals(["get", target, "length", obj], log[1]);
+  assertEquals(["has", target, "0"], log[2]);
+  assertEquals(["get", target, "0", obj], log[3]);
+  assertEquals(["has", target, "1"], log[4]);
+  assertEquals(["get", target, "1", obj], log[5]);
+  assertEquals(["has", target, "2"], log[6]);
+})();
+
+
+(function testUnspreadableArrayLikeProxy() {
+  var target = ["a", "b"];
+  target[Symbol.isConcatSpreadable] = "";
+  var obj = new Proxy(target, handler);
+
+  log.length = 0;
+  assertEquals([obj], [].concat(obj));
+  assertEquals(1, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+
+  log.length = 0;
+  assertEquals([obj], Array.prototype.concat.apply(obj));
+  assertEquals(1, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+})();
+
+
+(function testSpreadableArrayLikeProxy() {
+  var target = ["a", "b"];
+  target[Symbol.isConcatSpreadable] = undefined;
+  var obj = new Proxy(target, handler);
+
+  log.length = 0;
+  assertEquals(["a", "b"], [].concat(obj));
+  assertEquals(6, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+  assertEquals(["get", target, "length", obj], log[1]);
+  assertEquals(["has", target, "0"], log[2]);
+  assertEquals(["get", target, "0", obj], log[3]);
+  assertEquals(["has", target, "1"], log[4]);
+  assertEquals(["get", target, "1", obj], log[5]);
+
+  log.length = 0;
+  assertEquals(["a", "b"], Array.prototype.concat.apply(obj));
+  assertEquals(6, log.length);
+  for (var i in log) assertSame(target, log[i][1]);
+  assertEquals(["get", target, Symbol.isConcatSpreadable, obj], log[0]);
+  assertEquals(["get", target, "length", obj], log[1]);
+  assertEquals(["has", target, "0"], log[2]);
+  assertEquals(["get", target, "0", obj], log[3]);
+  assertEquals(["has", target, "1"], log[4]);
+  assertEquals(["get", target, "1", obj], log[5]);
+})();
+
+
+(function testSpreadableArrayLikeProxyWithNontrivialLength() {
+  var getTrap = function(t, key) {
+    if (key === "length") return {[Symbol.toPrimitive]() {return 3}};
+    if (key === "2") return "baz";
+    if (key === "3") return "bar";
+  };
+  var target = [];
+  var obj = new Proxy(target, {get: getTrap, has: () => true});
+
+  assertEquals([undefined, undefined, "baz"], [].concat(obj));
+  assertEquals([undefined, undefined, "baz"], Array.prototype.concat.apply(obj))
+})();
+
+
+(function testSpreadableArrayLikeProxyWithBogusLength() {
+  var getTrap = function(t, key) {
+    if (key === "length") return Symbol();
+    if (key === "2") return "baz";
+    if (key === "3") return "bar";
+  };
+  var target = [];
+  var obj = new Proxy(target, {get: getTrap, has: () => true});
+
+  assertThrows(() => [].concat(obj), TypeError);
+  assertThrows(() => Array.prototype.concat.apply(obj), TypeError);
+})();
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/es6/completion.js b/test/mjsunit/es6/completion.js
new file mode 100644
index 0000000..05565bf
--- /dev/null
+++ b/test/mjsunit/es6/completion.js
@@ -0,0 +1,150 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-sloppy-let --no-legacy-const
+
+
+function assertUndef(x) {
+  assertEquals(undefined, x);
+}
+
+
+// IfStatement [13.6.7]
+
+assertUndef(eval('42; if (true) ; else 0;'));  // ES5: 42
+assertUndef(eval('42; if (true) ;'));  // ES5: 42
+assertUndef(eval('42; if (false) 0;'));  // ES5: 42
+
+assertEquals(1, eval('42; if (true) 1;'));
+assertEquals(1, eval('42; if (true) 1; else 0;'));
+assertEquals(0, eval('42; if (false) 1; else 0;'));
+
+
+// IterationStatement [13.7]
+
+assertUndef(eval('42; do ; while (false);'));  // ES5: 42
+assertUndef(eval('42; var x = 1; do ; while (x--);'));  // ES5: 42
+assertUndef(eval('42; while (false) 0;'));  // ES5: 42
+assertUndef(eval('42; while (true) break;'));  // ES5: 42
+assertUndef(eval('42; bla: while (true) break bla;'));  // ES5: 42
+assertUndef(eval('42; var x = 1; while (x--) ;'));  // ES5: 42
+assertUndef(eval('42; for (; false; ) 0;'));  // ES5: 42
+assertUndef(eval('42; for (var x = 1; x; x--) ;'));  // ES5: 42
+assertUndef(eval('42; for (var x in ["foo", "bar"]) ;'));
+assertUndef(eval('42; for (var x of ["foo", "bar"]) ;'));
+assertUndef(eval('42; for (let x = 1; x; x--) ;'));
+assertUndef(eval('42; for (let x in ["foo", "bar"]) ;'));
+assertUndef(eval('42; for (let x of ["foo", "bar"]) ;'));
+assertUndef(eval('42; for (const x in ["foo", "bar"]) ;'));
+assertUndef(eval('42; for (const x of ["foo", "bar"]) ;'));
+
+assertEquals(1, eval('42; var x = 10; do x--; while (x);'));
+assertEquals(1, eval('42; var x = 10; while (x) x--;'));
+assertEquals(1, eval('42; for (var x = 10; x; x--) x;'));
+assertEquals(1, eval('42; for (var x = 10; x; --x) x;'));
+assertEquals(1, eval('42; for (let x = 10; x; --x) x;'));
+assertEquals(1, eval('42; var y = 2; for (var x in ["foo", "bar"]) y--;'));
+assertEquals(1, eval('42; var y = 2; for (const x in ["foo", "bar"]) y--;'));
+assertEquals(1, eval('42; var y = 2; for (let x in ["foo", "bar"]) y--;'));
+assertEquals(1, eval('42; var y = 2; for (var x of ["foo", "bar"]) y--;'));
+assertEquals(1, eval('42; var y = 2; for (const x of ["foo", "bar"]) y--;'));
+assertEquals(1, eval('42; var y = 2; for (let x of ["foo", "bar"]) y--;'));
+
+
+// WithStatement [13.11.7]
+
+assertUndef(eval('42; with ({}) ;'));  // ES5: 42
+
+assertEquals(1, eval('42; with ({}) 1;'));
+
+
+// SwitchStatement [13.12.11]
+
+assertUndef(eval('42; switch (0) {};'));  // ES5: 42
+assertUndef(eval('42; switch (0) { case 1: 1; };'));  // ES5: 42
+assertUndef(eval('42; switch (0) { case 0: ; };'));  // ES5: 42
+assertUndef(eval('42; switch (0) { default: ; };'));  // ES5: 42
+assertUndef(eval('42; switch (0) { case 0: break; }'));  // ES5: 42
+
+assertEquals(1, eval('42; switch (0) { case 0: 1; }'));
+assertEquals(1, eval('42; switch (0) { case 0: 1; break; }'));
+assertEquals(1, eval('42; switch (0) { case 0: 1; case 666: break; }'));
+assertEquals(2, eval('42; switch (0) { case 0: 1; case 666: 2; break; }'));
+
+
+// TryStatement [13.15.8]
+
+assertUndef(eval('42; try { } catch(e) { };'));  // ES5: 42
+assertUndef(eval('42; try { } catch(e) { 0; };'));  // ES5: 42
+assertUndef(eval('42; try { throw "" } catch(e) { };'));  // ES5: 42
+assertUndef(eval('42; try { throw "" } catch(e) { } finally { };'));  // ES5: 42
+assertUndef(eval('42; try { } finally { 666 };'));  // ES5: 42
+
+
+// Some combinations
+
+assertUndef(eval('42; switch (0) { case 0: if (true) break; }'));  // ES5: 42
+assertUndef(eval('42; switch (0) { case 0: 1; if (true) ; }'));  // ES5: 1
+assertUndef(eval('42; switch (0) { case 0: 1; try { break } catch(e) { }; }'));  // ES5: 1
+
+assertEquals(0, eval('42; switch (0) { case 0: 0; case 1: break; }'));
+assertEquals(0, eval('42; while (1) { 0; break; }'))
+assertEquals(0, eval('42; bla: while (1) { 0; break bla; }'))
+assertEquals(0, eval('42; while (1) { with ({}) { 0; break; } }'))
+assertEquals(0, eval('42; while (1) { try { 0; break } catch(e) {666} }'))
+assertEquals(0, eval(
+    '42; while (1) { try { 0; break } catch(e) {666} finally {666} }'))
+assertEquals(0, eval(
+    '42; while (1) { try { throw "" } catch(e) {666} finally {0; break} }'))
+assertEquals(0, eval(
+    '42; while (1) { try { throw "" } catch(e) {0; break} finally {666} }'))
+assertEquals(0, eval(
+    '42; while (1) { try { 666 } finally {0; break} }'));
+assertEquals(0, eval(
+    '42; while (1) { try { 666; break } finally {0; break} }'));
+assertEquals(0, eval(
+    '42; lab: try { 666; break lab } finally {0; break lab}'));
+assertEquals(undefined, eval(
+  'var b = 1; ' +
+  'outer: while (1) { while (1) { if (b--) 42; else break outer; }; 666 }'));
+
+// The following is not what ES6 says, but see ES bug 4540.
+assertUndef(eval('42; switch (0) { case 0: 1; if (true) break; }'));  // ES5: 1
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// The following are copied from webkit/eval-throw-return and adapted.
+
+function throwFunc() {
+  throw "";
+}
+
+function throwOnReturn(){
+  1;
+  return throwFunc();
+}
+
+function twoFunc() {
+  2;
+}
+
+assertEquals(1, eval("1;"));
+assertUndef(eval("1; try { foo = [2,3,throwFunc(), 4]; } catch (e){}"));
+assertUndef(eval("1; try { 2; throw ''; } catch (e){}"));
+assertUndef(eval("1; try { 2; throwFunc(); } catch (e){}"));
+assertEquals(3, eval("1; try { 2; throwFunc(); } catch (e){3;} finally {}"));
+assertEquals(3, eval("1; try { 2; throwFunc(); } catch (e){3;} finally {4;}"));
+assertUndef(eval("function blah() { 1; }; blah();"));
+assertUndef(eval("var x = 1;"));
+assertEquals(1, eval("if (true) { 1; } else { 2; }"));
+assertEquals(2, eval("if (false) { 1; } else { 2; }"));
+assertUndef(eval("try{1; if (true) { 2; throw ''; } else { 2; }} catch(e){}"));
+assertEquals(2, eval("1; var i = 0; do { ++i; 2; } while(i!=1);"));
+assertUndef(eval(
+    "try{1; var i = 0; do { ++i; 2; throw ''; } while (i!=1);} catch(e){}"));
+assertUndef(eval("1; try{2; throwOnReturn();} catch(e){}"));
+assertUndef(eval("1; twoFunc();"));
+assertEquals(2, eval("1; with ( { a: 0 } ) { 2; }"));
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");
 }