summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/arguments
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/arguments')
-rw-r--r--js/src/jit-test/tests/arguments/access-formals.js44
-rw-r--r--js/src/jit-test/tests/arguments/alias-function-closed.js167
-rw-r--r--js/src/jit-test/tests/arguments/alias-function-not-closed.js87
-rw-r--r--js/src/jit-test/tests/arguments/apply-args-obj-01.js18
-rw-r--r--js/src/jit-test/tests/arguments/apply-args-obj-02.js16
-rw-r--r--js/src/jit-test/tests/arguments/apply-args-obj-03.js20
-rw-r--r--js/src/jit-test/tests/arguments/apply-args-obj-04.js21
-rw-r--r--js/src/jit-test/tests/arguments/apply-closed-over-arguments-strict.js15
-rw-r--r--js/src/jit-test/tests/arguments/apply-closed-over-arguments.js14
-rw-r--r--js/src/jit-test/tests/arguments/apply-redefine-length.js18
-rw-r--r--js/src/jit-test/tests/arguments/args-attributes.js75
-rw-r--r--js/src/jit-test/tests/arguments/args-createontrace.js18
-rw-r--r--js/src/jit-test/tests/arguments/args-exists-own.js109
-rw-r--r--js/src/jit-test/tests/arguments/args-exists.js109
-rw-r--r--js/src/jit-test/tests/arguments/args-mochi-2.js23
-rw-r--r--js/src/jit-test/tests/arguments/args-mochi-2a.js23
-rw-r--r--js/src/jit-test/tests/arguments/args-mochi.js17
-rw-r--r--js/src/jit-test/tests/arguments/args-mutate-length-1.js16
-rw-r--r--js/src/jit-test/tests/arguments/args-mutate-length-2.js15
-rw-r--r--js/src/jit-test/tests/arguments/args-mutate-proto-1.js15
-rw-r--r--js/src/jit-test/tests/arguments/args-mutate-proto-2.js16
-rw-r--r--js/src/jit-test/tests/arguments/args-mutate-proto-3.js15
-rw-r--r--js/src/jit-test/tests/arguments/args-mutate-proto-4.js13
-rw-r--r--js/src/jit-test/tests/arguments/args-range-2.js37
-rw-r--r--js/src/jit-test/tests/arguments/args-range-const.js14
-rw-r--r--js/src/jit-test/tests/arguments/args-range.js18
-rw-r--r--js/src/jit-test/tests/arguments/args-redefine-iterator-1.js14
-rw-r--r--js/src/jit-test/tests/arguments/args-redefine-iterator-2.js14
-rw-r--r--js/src/jit-test/tests/arguments/args-redefine-length-1.js7
-rw-r--r--js/src/jit-test/tests/arguments/args-redefine-length-2.js8
-rw-r--r--js/src/jit-test/tests/arguments/args-redefine-length-3.js14
-rw-r--r--js/src/jit-test/tests/arguments/args-redefine-length-4.js14
-rw-r--r--js/src/jit-test/tests/arguments/args-redefine-length-5.js14
-rw-r--r--js/src/jit-test/tests/arguments/args-redefine-length-6.js14
-rw-r--r--js/src/jit-test/tests/arguments/args-redefine-length-7.js14
-rw-r--r--js/src/jit-test/tests/arguments/args-sum.js16
-rw-r--r--js/src/jit-test/tests/arguments/args-vargc.js18
-rw-r--r--js/src/jit-test/tests/arguments/args1.js15
-rw-r--r--js/src/jit-test/tests/arguments/args10.js16
-rw-r--r--js/src/jit-test/tests/arguments/args11.js14
-rw-r--r--js/src/jit-test/tests/arguments/args2.js20
-rw-r--r--js/src/jit-test/tests/arguments/args2a.js17
-rw-r--r--js/src/jit-test/tests/arguments/args2b.js17
-rw-r--r--js/src/jit-test/tests/arguments/args2c.js19
-rw-r--r--js/src/jit-test/tests/arguments/args2d.js17
-rw-r--r--js/src/jit-test/tests/arguments/args3.js20
-rw-r--r--js/src/jit-test/tests/arguments/args4.js21
-rw-r--r--js/src/jit-test/tests/arguments/args5.js24
-rw-r--r--js/src/jit-test/tests/arguments/args6.js22
-rw-r--r--js/src/jit-test/tests/arguments/args6a.js23
-rw-r--r--js/src/jit-test/tests/arguments/args7.js14
-rw-r--r--js/src/jit-test/tests/arguments/args8.js14
-rw-r--r--js/src/jit-test/tests/arguments/args9.js16
-rw-r--r--js/src/jit-test/tests/arguments/argsub.js13
-rw-r--r--js/src/jit-test/tests/arguments/argsx-1.js22
-rw-r--r--js/src/jit-test/tests/arguments/argsx-2.js23
-rw-r--r--js/src/jit-test/tests/arguments/argsx-3.js27
-rw-r--r--js/src/jit-test/tests/arguments/argsx-3a.js27
-rw-r--r--js/src/jit-test/tests/arguments/argsx-4.js23
-rw-r--r--js/src/jit-test/tests/arguments/arguments-on-proto.js27
-rw-r--r--js/src/jit-test/tests/arguments/bug-917585-relax-aliasing-constraints.js18
-rw-r--r--js/src/jit-test/tests/arguments/bug1051760.js4
-rw-r--r--js/src/jit-test/tests/arguments/bug1227287.js8
-rw-r--r--js/src/jit-test/tests/arguments/bug1423937.js16
-rw-r--r--js/src/jit-test/tests/arguments/bug1503071.js16
-rw-r--r--js/src/jit-test/tests/arguments/bug1621265.js17
-rw-r--r--js/src/jit-test/tests/arguments/bug1692833.js25
-rw-r--r--js/src/jit-test/tests/arguments/bug1696181.js15
-rw-r--r--js/src/jit-test/tests/arguments/bug1711414.js11
-rw-r--r--js/src/jit-test/tests/arguments/bug1749460.js14
-rw-r--r--js/src/jit-test/tests/arguments/bug1762575-1.js44
-rw-r--r--js/src/jit-test/tests/arguments/bug1762575-2.js50
-rw-r--r--js/src/jit-test/tests/arguments/bug1762575-3.js89
-rw-r--r--js/src/jit-test/tests/arguments/bug1825907.js7
-rw-r--r--js/src/jit-test/tests/arguments/bug1827073.js15
-rw-r--r--js/src/jit-test/tests/arguments/bug503772.js16
-rw-r--r--js/src/jit-test/tests/arguments/bug508178.js18
-rw-r--r--js/src/jit-test/tests/arguments/bug633020.js11
-rw-r--r--js/src/jit-test/tests/arguments/bug843985.js5
-rw-r--r--js/src/jit-test/tests/arguments/bug956173.js7
-rw-r--r--js/src/jit-test/tests/arguments/defaults-basic.js35
-rw-r--r--js/src/jit-test/tests/arguments/defaults-bound-to-function.js43
-rw-r--r--js/src/jit-test/tests/arguments/defaults-bug759904.js4
-rw-r--r--js/src/jit-test/tests/arguments/defaults-call-function.js15
-rw-r--r--js/src/jit-test/tests/arguments/defaults-destructuring-array.js17
-rw-r--r--js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js19
-rw-r--r--js/src/jit-test/tests/arguments/defaults-destructuring-function-expression.js9
-rw-r--r--js/src/jit-test/tests/arguments/defaults-destructuring-mixed-default-value.js55
-rw-r--r--js/src/jit-test/tests/arguments/defaults-destructuring-mixed.js29
-rw-r--r--js/src/jit-test/tests/arguments/defaults-destructuring-object.js27
-rw-r--r--js/src/jit-test/tests/arguments/defaults-destructuring-with-rest.js29
-rw-r--r--js/src/jit-test/tests/arguments/defaults-evaluation-order.js27
-rw-r--r--js/src/jit-test/tests/arguments/defaults-exceptions.js6
-rw-r--r--js/src/jit-test/tests/arguments/defaults-invalid-syntax.js30
-rw-r--r--js/src/jit-test/tests/arguments/defaults-scoping.js36
-rw-r--r--js/src/jit-test/tests/arguments/defaults-strict-mode.js41
-rw-r--r--js/src/jit-test/tests/arguments/defaults-with-arguments.js10
-rw-r--r--js/src/jit-test/tests/arguments/defaults-with-rest.js23
-rw-r--r--js/src/jit-test/tests/arguments/destructuring-after-defaults.js14
-rw-r--r--js/src/jit-test/tests/arguments/destructuring-default-value-scope.js10
-rw-r--r--js/src/jit-test/tests/arguments/destructuring-exprbody.js8
-rw-r--r--js/src/jit-test/tests/arguments/destructuring-with-rest.js21
-rw-r--r--js/src/jit-test/tests/arguments/dynamicBindings.js32
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-apply-forwarded.js18
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-apply.js17
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-callee.js13
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists-oob.js14
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists.js14
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-element-deleted-oob.js14
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-element-deleted.js14
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-element-exists-oob.js13
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-element-exists.js13
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-element-oob.js13
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-element.js13
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-inlined-apply.js14
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-inlined-slice-1.js15
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-inlined-slice-2.js15
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-inlined-slice-3.js15
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-inlined-slice-4.js15
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-inlined-spread.js14
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-length.js14
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-mutate-callee.js13
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-set-length.js14
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-slice-1.js18
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-slice-2.js18
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-slice-3.js18
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-slice-4.js18
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-1.js19
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-2.js19
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-3.js19
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-4.js19
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-spread-forwarded.js18
-rw-r--r--js/src/jit-test/tests/arguments/external-arguments-spread.js17
-rw-r--r--js/src/jit-test/tests/arguments/function_dot_caller_restrictions.js78
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-apply-rectifier.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-apply.js46
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-callee.js16
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-apply.js45
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-exists.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-oob.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-index-var.js44
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-length.js42
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-new-spread-optimization.js50
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-1.js50
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-2.js50
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-3.js50
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-4.js50
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-escaped-spread-optimization.js50
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-1.js34
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-2.js27
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-formals.js37
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-index-constant-exists.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-index-constant-oob.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-index-constant.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-index-var.js44
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-length.js42
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization-rectifier.js39
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization.js47
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-1.js39
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-2.js32
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-profiler.js11
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-slice-1.js46
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-slice-2.js46
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-slice-3.js46
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-slice-4.js46
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-slice-5.js97
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-1.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-2.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-3.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-4.js40
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-spread-optimization-rectifier.js39
-rw-r--r--js/src/jit-test/tests/arguments/inline-arguments-spread-optimization.js47
-rw-r--r--js/src/jit-test/tests/arguments/inline-rest-array-creation.js83
-rw-r--r--js/src/jit-test/tests/arguments/inline-transpile.js17
-rw-r--r--js/src/jit-test/tests/arguments/iterator-set-and-redefine.js33
-rw-r--r--js/src/jit-test/tests/arguments/mapped-define.js81
-rw-r--r--js/src/jit-test/tests/arguments/mapped-freeze.js8
-rw-r--r--js/src/jit-test/tests/arguments/mapped-unmapped-args.js61
-rw-r--r--js/src/jit-test/tests/arguments/nonstrict-args.js24
-rw-r--r--js/src/jit-test/tests/arguments/nonstrict-assign-element-get-parameter.js13
-rw-r--r--js/src/jit-test/tests/arguments/nonstrict-assign-parameter-get-element.js13
-rw-r--r--js/src/jit-test/tests/arguments/nonstrict-assign.js17
-rw-r--r--js/src/jit-test/tests/arguments/nonstrict-later-assign.js18
-rw-r--r--js/src/jit-test/tests/arguments/nonstrict-noargs.js21
-rw-r--r--js/src/jit-test/tests/arguments/polymorphic-getelem.js15
-rw-r--r--js/src/jit-test/tests/arguments/recover-osr-arguments-oob.js27
-rw-r--r--js/src/jit-test/tests/arguments/recover-osr-arguments.js27
-rw-r--r--js/src/jit-test/tests/arguments/recover-spread-opt-arguments-after-bail.js22
-rw-r--r--js/src/jit-test/tests/arguments/redefine-callee.js31
-rw-r--r--js/src/jit-test/tests/arguments/rest-alias-function.js10
-rw-r--r--js/src/jit-test/tests/arguments/rest-arguments-as-parameters.js9
-rw-r--r--js/src/jit-test/tests/arguments/rest-basic.js15
-rw-r--r--js/src/jit-test/tests/arguments/rest-bug763954.js5
-rw-r--r--js/src/jit-test/tests/arguments/rest-debugger.js17
-rw-r--r--js/src/jit-test/tests/arguments/rest-disallow-arguments-strict.js8
-rw-r--r--js/src/jit-test/tests/arguments/rest-in-Function.js3
-rw-r--r--js/src/jit-test/tests/arguments/rest-invalid-syntax.js12
-rw-r--r--js/src/jit-test/tests/arguments/rest-nested-arguments.js7
-rw-r--r--js/src/jit-test/tests/arguments/rest-nested.js7
-rw-r--r--js/src/jit-test/tests/arguments/rest-underflow.js9
-rw-r--r--js/src/jit-test/tests/arguments/rest-with-arguments.js40
-rw-r--r--js/src/jit-test/tests/arguments/slice-args-obj-01.js19
-rw-r--r--js/src/jit-test/tests/arguments/slice-args-obj-02.js17
-rw-r--r--js/src/jit-test/tests/arguments/slice-args-obj-03.js21
-rw-r--r--js/src/jit-test/tests/arguments/slice-args-obj-04.js22
-rw-r--r--js/src/jit-test/tests/arguments/slice-closed-over-arguments-strict.js17
-rw-r--r--js/src/jit-test/tests/arguments/slice-closed-over-arguments.js15
-rw-r--r--js/src/jit-test/tests/arguments/slice-redefine-length.js19
-rw-r--r--js/src/jit-test/tests/arguments/slice.js366
-rw-r--r--js/src/jit-test/tests/arguments/spread-args-obj-01.js18
-rw-r--r--js/src/jit-test/tests/arguments/spread-args-obj-02.js16
-rw-r--r--js/src/jit-test/tests/arguments/spread-args-obj-03.js20
-rw-r--r--js/src/jit-test/tests/arguments/spread-args-obj-04.js21
-rw-r--r--js/src/jit-test/tests/arguments/spread-call-optimization.js216
-rw-r--r--js/src/jit-test/tests/arguments/spread-closed-over-arguments-strict.js15
-rw-r--r--js/src/jit-test/tests/arguments/spread-closed-over-arguments.js14
-rw-r--r--js/src/jit-test/tests/arguments/spread-redefine-length.js18
-rw-r--r--js/src/jit-test/tests/arguments/strict-args-flushstack.js27
-rw-r--r--js/src/jit-test/tests/arguments/strict-args-generator-flushstack.js27
-rw-r--r--js/src/jit-test/tests/arguments/strict-args.js25
-rw-r--r--js/src/jit-test/tests/arguments/strict-assign-after.js28
-rw-r--r--js/src/jit-test/tests/arguments/strict-assign-arguments-element.js21
-rw-r--r--js/src/jit-test/tests/arguments/strict-assign-outer-param-psych.js27
-rw-r--r--js/src/jit-test/tests/arguments/strict-assign-outer-param.js27
-rw-r--r--js/src/jit-test/tests/arguments/strict-assign-parameter-get-element.js14
-rw-r--r--js/src/jit-test/tests/arguments/strict-assign.js26
-rw-r--r--js/src/jit-test/tests/arguments/strict-eval-mutation.js24
-rw-r--r--js/src/jit-test/tests/arguments/strict-eval.js30
-rw-r--r--js/src/jit-test/tests/arguments/strict-maybe-assign-outer.js26
-rw-r--r--js/src/jit-test/tests/arguments/strict-maybe-nested-eval.js26
-rw-r--r--js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-call.js33
-rw-r--r--js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-name.js33
-rw-r--r--js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function.js32
-rw-r--r--js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js39
-rw-r--r--js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch.js39
-rw-r--r--js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-var.js29
-rw-r--r--js/src/jit-test/tests/arguments/strict-nested-eval.js31
-rw-r--r--js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js30
-rw-r--r--js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js30
-rw-r--r--js/src/jit-test/tests/arguments/strict-noargs.js25
-rw-r--r--js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js13
-rw-r--r--js/src/jit-test/tests/arguments/testDelArg1.js13
-rw-r--r--js/src/jit-test/tests/arguments/testDelArg2.js13
-rw-r--r--js/src/jit-test/tests/arguments/testDelArg3.js42
-rw-r--r--js/src/jit-test/tests/arguments/testDelArg3Strict.js44
246 files changed, 6956 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/arguments/access-formals.js b/js/src/jit-test/tests/arguments/access-formals.js
new file mode 100644
index 0000000000..a63098500c
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/access-formals.js
@@ -0,0 +1,44 @@
+function g1(x, args) {
+ args[0] = 88;
+}
+
+// We assume we can optimize arguments access in |f|.
+//
+// Then the apply-call invalidates the arguments optimization,
+// and creates a real arguments object.
+//
+// Test that x and y fetch the values from the args object when
+// that happens.
+function f1(x, y, o) {
+ var res = 0;
+ for (var i=0; i<50; i++) {
+ res += x + y;
+ if (i > 10)
+ o.apply(null, arguments);
+ }
+ return res;
+}
+
+var o1 = {apply: g1};
+assertEq(f1(3, 5, o1), 3630);
+assertEq(f1(3, 5, o1), 3630);
+
+// In strict mode, the arguments object does not alias formals.
+function g2(x, args) {
+ args[0] = 88;
+}
+
+function f2(x, y, o) {
+ "use strict";
+ var res = 0;
+ for (var i=0; i<50; i++) {
+ res += x + y;
+ if (i > 10)
+ o.apply(null, arguments);
+ }
+ return res;
+}
+
+var o2 = {apply: g2};
+assertEq(f2(3, 5, o2), 400);
+assertEq(f2(3, 5, o2), 400);
diff --git a/js/src/jit-test/tests/arguments/alias-function-closed.js b/js/src/jit-test/tests/arguments/alias-function-closed.js
new file mode 100644
index 0000000000..ba91cc6f66
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/alias-function-closed.js
@@ -0,0 +1,167 @@
+function f1(a, aIs, // without default parameter
+ b=()=>62, bIs, // with default parameter
+ // before function body
+ c=(assertEq(a(), aIs), assertEq(b(), bIs),
+ ()=>63),
+ cIs) {
+ // before function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 53);
+ assertEq(c(), 55);
+
+ function a() {
+ return 52;
+ }
+ function c() {
+ return 54;
+ }
+ function g() {
+ // close here
+ assertEq(a(), 52); // after function declaration
+ assertEq(b(), 53); // before function declaration
+ assertEq(c(), 55); // before last function declaration
+ }
+ // function declaration after closed
+ function b() {
+ return 53;
+ }
+
+ assertEq(a(), 52); // after function declaration
+ assertEq(b(), 53); // after function declaration
+ assertEq(c(), 55); // before last function declaration
+
+ g();
+ c = ()=>72;
+ assertEq(c(), 72); // after assignment in body
+ h();
+ assertEq(c(), 82); // after assignment in closed function
+
+ function h() {
+ assertEq(c(), 72); // after assignment in body
+ c = ()=>82;
+ assertEq(c(), 82); // after assignment in closed function
+ }
+ // function re-declaration after closed and assignment
+ function c() {
+ return 55;
+ }
+}
+f1(()=>42, 42, undefined, 62, undefined, 63);
+f1(()=>42, 42, undefined, 62, ()=>44, 44);
+f1(()=>42, 42, ()=>43, 43, undefined, 63);
+f1(()=>42, 42, ()=>43, 43, ()=>44, 44);
+
+function f2(a, aIs,
+ // call before body
+ b=(function() { assertEq(a(), aIs); })(),
+ // a inside body not accessible from defaults
+ c=function() { assertEq(a(), 42); }) {
+ function a() {
+ return 52;
+ }
+ function g() {
+ // close here
+ assertEq(a(), 52);
+ }
+
+ assertEq(a(), 52);
+ g();
+ c();
+}
+f2(()=>42, 42);
+
+function f3(a, aIs,
+ // call before body
+ // close here
+ b=(function() { assertEq(a(), aIs); })(),
+ // a inside body not accessible from defaults
+ c=function() { assertEq(a(), 42); }) {
+ function a() {
+ return 52;
+ }
+
+ assertEq(a(), 52);
+ c();
+}
+f3(()=>42, 42);
+
+function f4(a,
+ // assignment before body
+ b=a=()=>62,
+ c=(assertEq(a(), 62)),
+ e=(assertEq(a(), 62))) {
+ function a() {
+ return 52;
+ }
+ function g() {
+ // close here
+ assertEq(a(), 52);
+ }
+
+ assertEq(a(), 52);
+ g();
+}
+f4(()=>42);
+
+function f5(a, b, c, d) {
+ // before var/function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 53);
+ assertEq(c(), 54);
+ assertEq(d(), 55);
+
+ function g() {
+ // before var/function declarations, called after var declarations
+ // close here
+ assertEq(a(), 52);
+ assertEq(b(), 63);
+ assertEq(c(), 54);
+ assertEq(d(), 65);
+ }
+
+ var a, b = ()=>63;
+ var c, d = ()=>65;
+
+ // after var declarations, before function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 63);
+ assertEq(c(), 54);
+ assertEq(d(), 65);
+
+ function h() {
+ // after var declarations, before function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 63);
+ assertEq(c(), 54);
+ assertEq(d(), 65);
+ }
+ function a() {
+ return 52;
+ }
+ function b() {
+ return 53;
+ }
+ function c() {
+ return 54;
+ }
+ function d() {
+ return 55;
+ }
+ function i() {
+ // after var/function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 63);
+ assertEq(c(), 54);
+ assertEq(d(), 65);
+ }
+
+ // after var/function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 63);
+ assertEq(c(), 54);
+ assertEq(d(), 65);
+ g();
+ h();
+ i();
+}
+f5(()=>42, ()=>43, ()=>44, ()=>45);
diff --git a/js/src/jit-test/tests/arguments/alias-function-not-closed.js b/js/src/jit-test/tests/arguments/alias-function-not-closed.js
new file mode 100644
index 0000000000..3de71f7c8e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/alias-function-not-closed.js
@@ -0,0 +1,87 @@
+function f1(a, aIs, // without default parameter
+ b=()=>62, bIs, // with default parameter
+ // before function body
+ c=(assertEq(a(), aIs), assertEq(b(), bIs),
+ ()=>63),
+ cIs) {
+ // before function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 53);
+ assertEq(c(), 55);
+
+ function a() {
+ return 52;
+ }
+ function b() {
+ return 53;
+ }
+ function c() {
+ return 54;
+ }
+
+ assertEq(a(), 52); // after function declaration
+ assertEq(b(), 53); // after function declaration
+ assertEq(c(), 55); // before last function declaration
+
+ c = ()=>72;
+ assertEq(c(), 72); // after assignment in body
+
+ // function re-declaration after assignment
+ function c() {
+ return 55;
+ }
+}
+f1(()=>42, 42, undefined, 62, undefined, 63);
+f1(()=>42, 42, undefined, 62, ()=>44, 44);
+f1(()=>42, 42, ()=>43, 43, undefined, 63);
+f1(()=>42, 42, ()=>43, 43, ()=>44, 44);
+
+function f2(a,
+ // assignment before body
+ b=a=()=>62,
+ c=(assertEq(a(), 62)),
+ e=(assertEq(a(), 62))) {
+ function a() {
+ return 52;
+ }
+
+ assertEq(a(), 52);
+}
+f2(()=>42);
+
+function f3(a, b, c, d) {
+ // before var/function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 53);
+ assertEq(c(), 54);
+ assertEq(d(), 55);
+
+ var a, b = ()=>63;
+ var c, d = ()=>65;
+
+ // after var declarations, before function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 63);
+ assertEq(c(), 54);
+ assertEq(d(), 65);
+
+ function a() {
+ return 52;
+ }
+ function b() {
+ return 53;
+ }
+ function c() {
+ return 54;
+ }
+ function d() {
+ return 55;
+ }
+
+ // after var/function declarations
+ assertEq(a(), 52);
+ assertEq(b(), 63);
+ assertEq(c(), 54);
+ assertEq(d(), 65);
+}
+f3(()=>42, ()=>43, ()=>44, ()=>45);
diff --git a/js/src/jit-test/tests/arguments/apply-args-obj-01.js b/js/src/jit-test/tests/arguments/apply-args-obj-01.js
new file mode 100644
index 0000000000..586787f963
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/apply-args-obj-01.js
@@ -0,0 +1,18 @@
+function escape(x) { with ({}) {} }
+
+function foo() {
+ escape(arguments);
+ return bar.apply({}, arguments);
+}
+
+function bar(x,y) {
+ return x + y;
+}
+
+with ({}) {}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/apply-args-obj-02.js b/js/src/jit-test/tests/arguments/apply-args-obj-02.js
new file mode 100644
index 0000000000..f619309818
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/apply-args-obj-02.js
@@ -0,0 +1,16 @@
+function foo() {
+ arguments[0] = 3;
+ return bar.apply({}, arguments);
+}
+
+function bar(x,y) {
+ return x + y;
+}
+
+with ({}) {}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 500);
diff --git a/js/src/jit-test/tests/arguments/apply-args-obj-03.js b/js/src/jit-test/tests/arguments/apply-args-obj-03.js
new file mode 100644
index 0000000000..03fe82f683
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/apply-args-obj-03.js
@@ -0,0 +1,20 @@
+function escape() { with ({}) {} }
+
+function foo(i) {
+ return i;
+}
+
+function bar(n) {
+ escape(arguments);
+ return foo.apply({}, arguments);
+}
+
+function baz(a, n) {
+ return bar(n);
+}
+
+var sum = 0;
+for (var i = 0; i < 10000; i++) {
+ sum += baz(0, 1);
+}
+assertEq(sum, 10000);
diff --git a/js/src/jit-test/tests/arguments/apply-args-obj-04.js b/js/src/jit-test/tests/arguments/apply-args-obj-04.js
new file mode 100644
index 0000000000..2a1e8b098e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/apply-args-obj-04.js
@@ -0,0 +1,21 @@
+var result;
+
+function g(a, b) {
+ with ({}) {}
+ result = a + b;
+}
+
+function escape() { with({}) {} }
+
+function f() {
+ escape(arguments);
+ for (var i = 0; i < 50; ++i) {
+ g.apply(this, arguments);
+ }
+}
+
+f(1, 2);
+assertEq(result, 3);
+
+f("");
+assertEq(result, "undefined");
diff --git a/js/src/jit-test/tests/arguments/apply-closed-over-arguments-strict.js b/js/src/jit-test/tests/arguments/apply-closed-over-arguments-strict.js
new file mode 100644
index 0000000000..71565cde94
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/apply-closed-over-arguments-strict.js
@@ -0,0 +1,15 @@
+'use strict'
+function bar(x,y) {
+ return x + y;
+}
+
+function foo(x, y) {
+ function closeOver() { return x; }
+ return bar.apply({}, arguments);
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300)
diff --git a/js/src/jit-test/tests/arguments/apply-closed-over-arguments.js b/js/src/jit-test/tests/arguments/apply-closed-over-arguments.js
new file mode 100644
index 0000000000..708d4cdb09
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/apply-closed-over-arguments.js
@@ -0,0 +1,14 @@
+function bar(x,y) {
+ return x + y;
+}
+
+function foo(x, y) {
+ function closeOver() { return x; }
+ return bar.apply({}, arguments);
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300)
diff --git a/js/src/jit-test/tests/arguments/apply-redefine-length.js b/js/src/jit-test/tests/arguments/apply-redefine-length.js
new file mode 100644
index 0000000000..4dd5cb68d7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/apply-redefine-length.js
@@ -0,0 +1,18 @@
+function foo() {
+ arguments.length = 2;
+ return bar.apply({}, arguments);
+}
+
+function bar() {
+ var result = 0;
+ for (var x of arguments) {
+ result += x;
+ }
+ return result;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2,3,4,5,6);
+}
+assertEq(sum,300);
diff --git a/js/src/jit-test/tests/arguments/args-attributes.js b/js/src/jit-test/tests/arguments/args-attributes.js
new file mode 100644
index 0000000000..5182202371
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-attributes.js
@@ -0,0 +1,75 @@
+function strictArgs() {
+ return (function (a, b, c) {'use strict'; return arguments; })(1, 2);
+}
+
+function normalArgs() {
+ return (function (a, b, c) { return arguments; })(1, 2);
+}
+
+function checkProperty(options, prop, shouldThrow) {
+ var desc, orig;
+ var obj = options.strict ? strictArgs() : normalArgs();
+ var objType = options.strict ? "strict arguments." : "normal arguments.";
+
+ function check() {
+ orig = Object.getOwnPropertyDescriptor(obj, prop);
+
+ var threw = false;
+ try {
+ obj[prop] = obj[prop];
+ }
+ catch (e) {
+ threw = true;
+ }
+ assertEq(threw, shouldThrow, objType + prop + " threw");
+
+ if (orig === undefined) {
+ // The property wasn't defined, so we can skip it.
+ return;
+ }
+
+ desc = Object.getOwnPropertyDescriptor(obj, prop);
+ if ("value" in orig) {
+ assertEq(desc.value, orig.value, objType + prop + " value");
+ } else {
+ assertEq(desc.get, orig.get, objType + prop + " get");
+ assertEq(desc.set, orig.set, objType + prop + " set");
+ }
+ assertEq(desc.writable, orig.writable, objType + prop + " writable");
+ assertEq(desc.enumerable, orig.enumerable, objType + prop + " enumerable");
+ assertEq(desc.configurable, orig.configurable, objType + prop + " configurable");
+ }
+
+ check();
+
+ if (orig && orig.configurable) {
+ if(options.refresh) { obj = options.strict ? strictArgs() : normalArgs(); }
+ Object.defineProperty(obj, prop, {writable: false, enumerable: true});
+ check();
+
+ if(options.refresh) { obj = options.strict ? strictArgs() : normalArgs(); }
+ Object.defineProperty(obj, prop, {writable: true, enumerable: false});
+ check();
+
+ if(options.refresh) { obj = options.strict ? strictArgs() : normalArgs(); }
+ Object.defineProperty(obj, prop, {writable: false, configurable: false});
+ check();
+ }
+}
+
+checkProperty({strict: true, refresh: true}, 'callee', true);
+checkProperty({strict: true, refresh: false}, 'callee', true);
+checkProperty({strict: false, refresh: true}, 'callee', false);
+checkProperty({strict: false, refresh: false}, 'callee', false);
+
+checkProperty({strict: true, refresh: true}, 'length', false);
+checkProperty({strict: true, refresh: false}, 'length', false);
+checkProperty({strict: false, refresh: true}, 'length', false);
+checkProperty({strict: false, refresh: false}, 'length', false);
+
+for (var i = 0; i <= 5; i++) {
+ checkProperty({strict: true, refresh: true}, "" + i, false);
+ checkProperty({strict: true, refresh: false}, "" + i, false);
+ checkProperty({strict: false, refresh: true}, "" + i, false);
+ checkProperty({strict: false, refresh: false}, "" + i, false);
+}
diff --git a/js/src/jit-test/tests/arguments/args-createontrace.js b/js/src/jit-test/tests/arguments/args-createontrace.js
new file mode 100644
index 0000000000..9f9f0a4082
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-createontrace.js
@@ -0,0 +1,18 @@
+actual = '';
+expected = '5,4,3,2,1,X,5,4,3,2,1,Y,5,4,3,2,1,';
+
+function f() {
+ for (var i = 0; i < 5; ++i) {
+ var args = arguments;
+ appendToActual(args[i]);
+ }
+}
+
+f(5, 4, 3, 2, 1);
+appendToActual("X");
+f(5, 4, 3, 2, 1);
+appendToActual("Y");
+f(5, 4, 3, 2, 1);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-exists-own.js b/js/src/jit-test/tests/arguments/args-exists-own.js
new file mode 100644
index 0000000000..937c26608e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-exists-own.js
@@ -0,0 +1,109 @@
+// Test |Object.hasOwn| on arguments objects.
+
+function testBasic() {
+ function arg0() { return Object.hasOwn(arguments, 0); }
+ function arg1() { return Object.hasOwn(arguments, 1); }
+ function arg100() { return Object.hasOwn(arguments, 100); }
+ function argn1() { return Object.hasOwn(arguments, -1); }
+ function argv(i) { return Object.hasOwn(arguments, i); }
+
+ for (let i = 0; i < 100; ++i) {
+ assertEq(arg0(), false);
+ assertEq(arg0(1), true);
+ assertEq(arg0(1, 2), true);
+ assertEq(arg0(1, 2, 3), true);
+ assertEq(arg0(1, 2, 3, 4), true);
+ assertEq(arg0(1, 2, 3, 4, 5), true);
+
+ assertEq(arg1(), false);
+ assertEq(arg1(1), false);
+ assertEq(arg1(1, 2), true);
+ assertEq(arg1(1, 2, 3), true);
+ assertEq(arg1(1, 2, 3, 4), true);
+ assertEq(arg1(1, 2, 3, 4, 5), true);
+
+ assertEq(arg100(), false);
+ assertEq(arg100(1), false);
+ assertEq(arg100(1, 2), false);
+ assertEq(arg100(1, 2, 3), false);
+ assertEq(arg100(1, 2, 3, 4), false);
+ assertEq(arg100(1, 2, 3, 4, 5), false);
+
+ assertEq(argn1(), false);
+ assertEq(argn1(1), false);
+ assertEq(argn1(1, 2), false);
+ assertEq(argn1(1, 2, 3), false);
+ assertEq(argn1(1, 2, 3, 4), false);
+ assertEq(argn1(1, 2, 3, 4, 5), false);
+
+ assertEq(argv(i & 3), (i&3) <= 0);
+ assertEq(argv(i & 3, 1), (i&3) <= 1);
+ assertEq(argv(i & 3, 1, 2), (i&3) <= 2);
+ assertEq(argv(i & 3, 1, 2, 3), true);
+ assertEq(argv(i & 3, 1, 2, 3, 4), true);
+ assertEq(argv(i & 3, 1, 2, 3, 4, 5), true);
+ }
+}
+testBasic();
+
+// Modifying |arguments.length| doesn't change the result.
+function testOverriddenLength() {
+ function f(i) {
+ if (i === 100) {
+ arguments.length = 100;
+ }
+ return Object.hasOwn(arguments, 1);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i), false);
+ }
+}
+testOverriddenLength();
+
+// Overridden elements are correctly detected.
+function testOverriddenElement() {
+ function f(i) {
+ if (i === 100) {
+ arguments[1] = 0;
+ }
+ return Object.hasOwn(arguments, 1);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i), i === 100);
+ }
+}
+testOverriddenElement();
+
+// Deleted elements are correctly detected.
+function testDeletedElement() {
+ function f(i) {
+ if (i === 100) {
+ delete arguments[0];
+ }
+ return Object.hasOwn(arguments, 0);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i), i !== 100);
+ }
+}
+testDeletedElement();
+
+// Contrary to most other arguments object optimisations, forwarded arguments
+// don't inhibit optimising |Object.hasOwn|.
+function testForwardedArg() {
+ function f(i) {
+ function closedOver() {
+ if (i === 100) i = 0;
+ }
+ closedOver();
+ return Object.hasOwn(arguments, 0);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i), true);
+ }
+}
+testForwardedArg();
diff --git a/js/src/jit-test/tests/arguments/args-exists.js b/js/src/jit-test/tests/arguments/args-exists.js
new file mode 100644
index 0000000000..35ea8e20bb
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-exists.js
@@ -0,0 +1,109 @@
+// Test |in| operator on arguments objects.
+
+function testBasic() {
+ function arg0() { return 0 in arguments; }
+ function arg1() { return 1 in arguments; }
+ function arg100() { return 100 in arguments; }
+ function argn1() { return -1 in arguments; }
+ function argv(i) { return i in arguments; }
+
+ for (let i = 0; i < 100; ++i) {
+ assertEq(arg0(), false);
+ assertEq(arg0(1), true);
+ assertEq(arg0(1, 2), true);
+ assertEq(arg0(1, 2, 3), true);
+ assertEq(arg0(1, 2, 3, 4), true);
+ assertEq(arg0(1, 2, 3, 4, 5), true);
+
+ assertEq(arg1(), false);
+ assertEq(arg1(1), false);
+ assertEq(arg1(1, 2), true);
+ assertEq(arg1(1, 2, 3), true);
+ assertEq(arg1(1, 2, 3, 4), true);
+ assertEq(arg1(1, 2, 3, 4, 5), true);
+
+ assertEq(arg100(), false);
+ assertEq(arg100(1), false);
+ assertEq(arg100(1, 2), false);
+ assertEq(arg100(1, 2, 3), false);
+ assertEq(arg100(1, 2, 3, 4), false);
+ assertEq(arg100(1, 2, 3, 4, 5), false);
+
+ assertEq(argn1(), false);
+ assertEq(argn1(1), false);
+ assertEq(argn1(1, 2), false);
+ assertEq(argn1(1, 2, 3), false);
+ assertEq(argn1(1, 2, 3, 4), false);
+ assertEq(argn1(1, 2, 3, 4, 5), false);
+
+ assertEq(argv(i & 3), (i&3) <= 0);
+ assertEq(argv(i & 3, 1), (i&3) <= 1);
+ assertEq(argv(i & 3, 1, 2), (i&3) <= 2);
+ assertEq(argv(i & 3, 1, 2, 3), true);
+ assertEq(argv(i & 3, 1, 2, 3, 4), true);
+ assertEq(argv(i & 3, 1, 2, 3, 4, 5), true);
+ }
+}
+testBasic();
+
+// Modifying |arguments.length| doesn't change the result.
+function testOverriddenLength() {
+ function f(i) {
+ if (i === 100) {
+ arguments.length = 100;
+ }
+ return 1 in arguments;
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i), false);
+ }
+}
+testOverriddenLength();
+
+// Overridden elements are correctly detected.
+function testOverriddenElement() {
+ function f(i) {
+ if (i === 100) {
+ arguments[1] = 0;
+ }
+ return 1 in arguments;
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i), i === 100);
+ }
+}
+testOverriddenElement();
+
+// Deleted elements are correctly detected.
+function testDeletedElement() {
+ function f(i) {
+ if (i === 100) {
+ delete arguments[0];
+ }
+ return 0 in arguments;
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i), i !== 100);
+ }
+}
+testDeletedElement();
+
+// Contrary to most other arguments object optimisations, forwarded arguments
+// don't inhibit optimising the |in| operator.
+function testForwardedArg() {
+ function f(i) {
+ function closedOver() {
+ if (i === 100) i = 0;
+ }
+ closedOver();
+ return 0 in arguments;
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i), true);
+ }
+}
+testForwardedArg();
diff --git a/js/src/jit-test/tests/arguments/args-mochi-2.js b/js/src/jit-test/tests/arguments/args-mochi-2.js
new file mode 100644
index 0000000000..4fec2dd9b0
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-mochi-2.js
@@ -0,0 +1,23 @@
+actual = '';
+expected = 'true,';
+
+var isNotEmpty = function (args, i) {
+ var o = args[i];
+ if (!(o && o.length)) {
+ return false;
+ }
+ return true;
+};
+
+var f = function(obj) {
+ for (var i = 0; i < arguments.length; i++) {
+ if (!isNotEmpty(arguments, i))
+ return false;
+ }
+ return true;
+}
+
+appendToActual(f([1], [1], [1], "asdf", [1]));
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-mochi-2a.js b/js/src/jit-test/tests/arguments/args-mochi-2a.js
new file mode 100644
index 0000000000..5c8895b15a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-mochi-2a.js
@@ -0,0 +1,23 @@
+actual = '';
+expected = 'true,';
+
+function isNotEmpty(args, i) {
+ var o = args[i];
+ if (!(o && o.length)) {
+ return false;
+ }
+ return true;
+};
+
+function f(obj) {
+ for (var i = 0; i < arguments.length; i++) {
+ if (!isNotEmpty(arguments, i))
+ return false;
+ }
+ return true;
+}
+
+appendToActual(f([1], [1], [1], "asdf", [1]));
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-mochi.js b/js/src/jit-test/tests/arguments/args-mochi.js
new file mode 100644
index 0000000000..c477ef0972
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-mochi.js
@@ -0,0 +1,17 @@
+actual = '';
+expected = 'true,';
+
+var isNotEmpty = function (obj) {
+ for (var i = 0; i < arguments.length; i++) {
+ var o = arguments[i];
+ if (!(o && o.length)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+appendToActual(isNotEmpty([1], [1], [1], "asdf", [1]));
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-mutate-length-1.js b/js/src/jit-test/tests/arguments/args-mutate-length-1.js
new file mode 100644
index 0000000000..cea55bc36a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-mutate-length-1.js
@@ -0,0 +1,16 @@
+actual = '';
+expected = '0,0,0,';
+
+function f() {
+ arguments.length--;
+ for (var i = 0; i < arguments.length; ++i) {
+ appendToActual(i);
+ }
+}
+
+f(1, 2);
+f(1, 2);
+f(2, 2);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-mutate-length-2.js b/js/src/jit-test/tests/arguments/args-mutate-length-2.js
new file mode 100644
index 0000000000..1db881b423
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-mutate-length-2.js
@@ -0,0 +1,15 @@
+actual = '';
+expected = '0,1,0,1,0,1,';
+
+function f() {
+ for (var i = 0; i < arguments.length; ++i) {
+ appendToActual(i);
+ }
+}
+
+f(1, 2);
+f(1, 2);
+f(2, 2);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-mutate-proto-1.js b/js/src/jit-test/tests/arguments/args-mutate-proto-1.js
new file mode 100644
index 0000000000..fc3b8c5b23
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-mutate-proto-1.js
@@ -0,0 +1,15 @@
+function outOfBounds() {
+ var proto = ["pass"];
+
+ var N = 100;
+ for (var i = 0; i <= N; ++i) {
+ if (i === N) {
+ Object.setPrototypeOf(arguments, proto);
+ }
+
+ var arg = arguments[0];
+
+ assertEq(arg, i !== N ? undefined : "pass");
+ }
+}
+outOfBounds();
diff --git a/js/src/jit-test/tests/arguments/args-mutate-proto-2.js b/js/src/jit-test/tests/arguments/args-mutate-proto-2.js
new file mode 100644
index 0000000000..9645f88090
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-mutate-proto-2.js
@@ -0,0 +1,16 @@
+function outOfBounds() {
+ var proto = [];
+ Object.setPrototypeOf(arguments, proto);
+
+ var N = 100;
+ for (var i = 0; i <= N; ++i) {
+ if (i === N) {
+ proto[0] = "pass";
+ }
+
+ var arg = arguments[0];
+
+ assertEq(arg, i !== N ? undefined : "pass");
+ }
+}
+outOfBounds();
diff --git a/js/src/jit-test/tests/arguments/args-mutate-proto-3.js b/js/src/jit-test/tests/arguments/args-mutate-proto-3.js
new file mode 100644
index 0000000000..ccfb924dec
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-mutate-proto-3.js
@@ -0,0 +1,15 @@
+function outOfBounds() {
+ Object.setPrototypeOf(arguments, Array.prototype);
+
+ var N = 100;
+ for (var i = 0; i <= N; ++i) {
+ if (i === N) {
+ Array.prototype[0] = "pass";
+ }
+
+ var arg = arguments[0];
+
+ assertEq(arg, i !== N ? undefined : "pass");
+ }
+}
+outOfBounds();
diff --git a/js/src/jit-test/tests/arguments/args-mutate-proto-4.js b/js/src/jit-test/tests/arguments/args-mutate-proto-4.js
new file mode 100644
index 0000000000..d971669ca8
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-mutate-proto-4.js
@@ -0,0 +1,13 @@
+function outOfBounds() {
+ var N = 100;
+ for (var i = 0; i <= N; ++i) {
+ if (i === N) {
+ Object.prototype[0] = "pass";
+ }
+
+ var arg = arguments[0];
+
+ assertEq(arg, i !== N ? undefined : "pass");
+ }
+}
+outOfBounds();
diff --git a/js/src/jit-test/tests/arguments/args-range-2.js b/js/src/jit-test/tests/arguments/args-range-2.js
new file mode 100644
index 0000000000..393d574df5
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-range-2.js
@@ -0,0 +1,37 @@
+actual = '';
+expected = "undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,";
+
+var index;
+
+function h() {
+ for (var i = 0; i < 5; ++i) {
+ var a = arguments;
+ appendToActual(a[index]);
+ }
+}
+
+index = 0;
+h();
+index = -1;
+h();
+index = 1;
+h();
+
+index = -9999999;
+h(1, 2, 3);
+index = -1;
+h(1, 2, 3);
+index = 0;
+h(1, 2, 3);
+index = 1;
+h(1, 2, 3);
+index = 2;
+h(1, 2, 3);
+index = 3;
+h(1, 2, 3);
+index = 4;
+h(1, 2, 3);
+index = 9999999;
+h(1, 2, 3);
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-range-const.js b/js/src/jit-test/tests/arguments/args-range-const.js
new file mode 100644
index 0000000000..d4a9193b9e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-range-const.js
@@ -0,0 +1,14 @@
+actual = '';
+expected = 'undefined,undefined,undefined,undefined,undefined,';
+
+function h() {
+ for (var i = 0; i < 5; ++i) {
+ var a = arguments;
+ appendToActual(a[100]);
+ }
+}
+
+h();
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-range.js b/js/src/jit-test/tests/arguments/args-range.js
new file mode 100644
index 0000000000..a5e40acaab
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-range.js
@@ -0,0 +1,18 @@
+actual = '';
+expected = '0,0,0,0,0,88,88,88,88,88,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,';
+
+function h(k) {
+ for (var i = 0; i < 5; ++i) {
+ var a = arguments;
+ appendToActual(a[k]);
+ }
+}
+
+h(0);
+h(2, 99, 88, 77);
+h(-5);
+h(46);
+h('adf');
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-redefine-iterator-1.js b/js/src/jit-test/tests/arguments/args-redefine-iterator-1.js
new file mode 100644
index 0000000000..77241a6ae7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-redefine-iterator-1.js
@@ -0,0 +1,14 @@
+function t()
+{
+ var a = arguments;
+ Object.defineProperty(a, Symbol.iterator, { });
+ for (var i = 0; i < 5; i++)
+ assertEq(a[Symbol.iterator], Array.prototype[Symbol.iterator]);
+
+ var desc = Object.getOwnPropertyDescriptor(a, Symbol.iterator);
+ assertEq(desc.value, Array.prototype[Symbol.iterator]);
+ assertEq(desc.writable, true);
+ assertEq(desc.enumerable, false);
+ assertEq(desc.configurable, true);
+}
+t();
diff --git a/js/src/jit-test/tests/arguments/args-redefine-iterator-2.js b/js/src/jit-test/tests/arguments/args-redefine-iterator-2.js
new file mode 100644
index 0000000000..186be930c4
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-redefine-iterator-2.js
@@ -0,0 +1,14 @@
+function t()
+{
+ var a = arguments;
+ Object.defineProperty(a, Symbol.iterator, { writable: false, enumerable: true, configurable: false });
+ for (var i = 0; i < 5; i++)
+ assertEq(a[Symbol.iterator], Array.prototype[Symbol.iterator]);
+
+ var desc = Object.getOwnPropertyDescriptor(a, Symbol.iterator);
+ assertEq(desc.value, Array.prototype[Symbol.iterator]);
+ assertEq(desc.writable, false);
+ assertEq(desc.enumerable, true);
+ assertEq(desc.configurable, false);
+}
+t();
diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-1.js b/js/src/jit-test/tests/arguments/args-redefine-length-1.js
new file mode 100644
index 0000000000..c71c97b1cb
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-redefine-length-1.js
@@ -0,0 +1,7 @@
+function t()
+{
+ Object.defineProperty(arguments, "length", { value: 17 });
+ for (var i = 0; i < 5; i++)
+ assertEq(arguments.length, 17);
+}
+t();
diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-2.js b/js/src/jit-test/tests/arguments/args-redefine-length-2.js
new file mode 100644
index 0000000000..fe1c9cf2fe
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-redefine-length-2.js
@@ -0,0 +1,8 @@
+function t()
+{
+ var a = arguments;
+ Object.defineProperty(a, "length", { value: 17 });
+ for (var i = 0; i < 5; i++)
+ assertEq(a.length, 17);
+}
+t();
diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-3.js b/js/src/jit-test/tests/arguments/args-redefine-length-3.js
new file mode 100644
index 0000000000..a4d6823acf
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-redefine-length-3.js
@@ -0,0 +1,14 @@
+function t()
+{
+ var a = arguments;
+ Object.defineProperty(a, "length", { });
+ for (var i = 0; i < 5; i++)
+ assertEq(a.length, 0);
+
+ var desc = Object.getOwnPropertyDescriptor(a, "length");
+ assertEq(desc.value, 0);
+ assertEq(desc.writable, true);
+ assertEq(desc.enumerable, false);
+ assertEq(desc.configurable, true);
+}
+t();
diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-4.js b/js/src/jit-test/tests/arguments/args-redefine-length-4.js
new file mode 100644
index 0000000000..1029e8fca3
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-redefine-length-4.js
@@ -0,0 +1,14 @@
+function t()
+{
+ var a = arguments;
+ Object.defineProperty(a, "length", { writable: false });
+ for (var i = 0; i < 5; i++)
+ assertEq(a.length, 0);
+
+ var desc = Object.getOwnPropertyDescriptor(a, "length");
+ assertEq(desc.value, 0);
+ assertEq(desc.writable, false);
+ assertEq(desc.enumerable, false);
+ assertEq(desc.configurable, true);
+}
+t();
diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-5.js b/js/src/jit-test/tests/arguments/args-redefine-length-5.js
new file mode 100644
index 0000000000..2ae30bf0f7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-redefine-length-5.js
@@ -0,0 +1,14 @@
+function t()
+{
+ var a = arguments;
+ Object.defineProperty(a, "length", { enumerable: true });
+ for (var i = 0; i < 5; i++)
+ assertEq(a.length, 0);
+
+ var desc = Object.getOwnPropertyDescriptor(a, "length");
+ assertEq(desc.value, 0);
+ assertEq(desc.writable, true);
+ assertEq(desc.enumerable, true);
+ assertEq(desc.configurable, true);
+}
+t();
diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-6.js b/js/src/jit-test/tests/arguments/args-redefine-length-6.js
new file mode 100644
index 0000000000..a4b768d4bd
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-redefine-length-6.js
@@ -0,0 +1,14 @@
+function t()
+{
+ var a = arguments;
+ Object.defineProperty(a, "length", { configurable: false });
+ for (var i = 0; i < 5; i++)
+ assertEq(a.length, 0);
+
+ var desc = Object.getOwnPropertyDescriptor(a, "length");
+ assertEq(desc.value, 0);
+ assertEq(desc.writable, true);
+ assertEq(desc.enumerable, false);
+ assertEq(desc.configurable, false);
+}
+t();
diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-7.js b/js/src/jit-test/tests/arguments/args-redefine-length-7.js
new file mode 100644
index 0000000000..042b224740
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-redefine-length-7.js
@@ -0,0 +1,14 @@
+function t()
+{
+ var a = arguments;
+ Object.defineProperty(a, "length", { value: 0 });
+ for (var i = 0; i < 5; i++)
+ assertEq(a.length, 0);
+
+ var desc = Object.getOwnPropertyDescriptor(a, "length");
+ assertEq(desc.value, 0);
+ assertEq(desc.writable, true);
+ assertEq(desc.enumerable, false);
+ assertEq(desc.configurable, true);
+}
+t();
diff --git a/js/src/jit-test/tests/arguments/args-sum.js b/js/src/jit-test/tests/arguments/args-sum.js
new file mode 100644
index 0000000000..04946e0fe8
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-sum.js
@@ -0,0 +1,16 @@
+actual = '';
+expected = '666,';
+
+function h() {
+ var ans = 0;
+ for (var i = 0; i < arguments.length; ++i) {
+ ans += arguments[i];
+ }
+ return ans;
+}
+
+var q = h(600, 60, 6);
+appendToActual(q);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args-vargc.js b/js/src/jit-test/tests/arguments/args-vargc.js
new file mode 100644
index 0000000000..615323c48a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args-vargc.js
@@ -0,0 +1,18 @@
+actual = '';
+expected = '1 2,1 2,1 2,1 2,1 2,1 2,1 2,1 2,1 undefined,1 undefined,1 undefined,1 undefined,1 undefined,1 undefined,1 undefined,1 undefined,';
+
+function g(a, b) {
+ appendToActual(a + ' ' + b);
+}
+
+function f() {
+ for (var i = 0; i < 8; ++i) {
+ g.apply(this, arguments);
+ }
+}
+
+f(1, 2);
+f(1);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args1.js b/js/src/jit-test/tests/arguments/args1.js
new file mode 100644
index 0000000000..3efc2994cf
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args1.js
@@ -0,0 +1,15 @@
+actual = '';
+expected = 'a,';
+
+function f() {
+ arguments;
+}
+
+for (var i = 0; i < 1000; ++i) {
+ f(1, 2);
+}
+
+appendToActual('a')
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args10.js b/js/src/jit-test/tests/arguments/args10.js
new file mode 100644
index 0000000000..4f31084e06
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args10.js
@@ -0,0 +1,16 @@
+actual = '';
+expected = 'function h(x, y) { return arguments; },2,4,8,';
+
+function h(x, y) { return arguments; }
+
+var p;
+for (var i = 0; i < 5; ++i) {
+ p = h(i, i*2);
+}
+appendToActual(p.callee);
+appendToActual(p.length);
+appendToActual(p[0]);
+appendToActual(p[1]);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args11.js b/js/src/jit-test/tests/arguments/args11.js
new file mode 100644
index 0000000000..13e5893a5d
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args11.js
@@ -0,0 +1,14 @@
+actual = '';
+expected = 'true,true,true,true,true,';
+
+function h() {
+ var a = arguments;
+ for (var i = 0; i < 5; ++i) {
+ appendToActual(a == arguments);
+ }
+}
+
+h();
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args2.js b/js/src/jit-test/tests/arguments/args2.js
new file mode 100644
index 0000000000..2c19c3198e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args2.js
@@ -0,0 +1,20 @@
+actual = '';
+expected = '151,';
+
+var g = 0;
+
+function add(a, b) {
+ g = a + b;
+}
+
+function f() {
+ add.apply(this, arguments);
+}
+
+for (var i = 0; i < 5; ++i) {
+ f(100, 51);
+}
+appendToActual(g);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args2a.js b/js/src/jit-test/tests/arguments/args2a.js
new file mode 100644
index 0000000000..627aef0eb8
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args2a.js
@@ -0,0 +1,17 @@
+actual = '';
+expected = 'g,g,g,g,g,';
+
+function g() {
+ appendToActual('g');
+}
+
+function f() {
+ g.apply(this, arguments);
+}
+
+for (var i = 0; i < 5; ++i) {
+ f();
+}
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args2b.js b/js/src/jit-test/tests/arguments/args2b.js
new file mode 100644
index 0000000000..aa477863e7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args2b.js
@@ -0,0 +1,17 @@
+actual = '';
+expected = 'g 0,g 1,g 2,g 3,g 4,';
+
+function g(x) {
+ appendToActual('g ' + x);
+}
+
+function f() {
+ g.apply(this, arguments);
+}
+
+for (var i = 0; i < 5; ++i) {
+ f(i);
+}
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args2c.js b/js/src/jit-test/tests/arguments/args2c.js
new file mode 100644
index 0000000000..9e83a424dc
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args2c.js
@@ -0,0 +1,19 @@
+actual = '';
+expected = 'g 0 0,g 1 2,g 2 4,g 3 6,g 4 8,';
+
+function g(x, y) {
+ appendToActual('g ' + x + ' ' + y);
+ //appendToActual('g ' + x + ' ' + y);
+ //appendToActual('g ' + y);
+}
+
+function f() {
+ g.apply(this, arguments);
+}
+
+for (var i = 0; i < 5; ++i) {
+ f(i, i*2);
+}
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args2d.js b/js/src/jit-test/tests/arguments/args2d.js
new file mode 100644
index 0000000000..a95c821fe6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args2d.js
@@ -0,0 +1,17 @@
+actual = '';
+expected = 'g 0 0 0,g 1 2 1,g 2 4 4,g 3 6 9,g 4 8 16,';
+
+function g(x, y, z) {
+ appendToActual('g ' + x + ' ' + y + ' ' + z);
+}
+
+function f() {
+ g.apply(this, arguments);
+}
+
+for (var i = 0; i < 5; ++i) {
+ f(i, i*2, i*i);
+}
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args3.js b/js/src/jit-test/tests/arguments/args3.js
new file mode 100644
index 0000000000..7098521222
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args3.js
@@ -0,0 +1,20 @@
+actual = '';
+expected = '51,';
+
+var g = 0;
+
+function add(a, b) {
+ g = a + b;
+}
+
+function f() {
+ g = arguments[1];
+}
+
+for (var i = 0; i < 10000; ++i) {
+ f(100, 51);
+}
+appendToActual(g);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args4.js b/js/src/jit-test/tests/arguments/args4.js
new file mode 100644
index 0000000000..bd13c88156
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args4.js
@@ -0,0 +1,21 @@
+actual = '';
+expected = '51,';
+
+var g = 0;
+
+function h(args) {
+ g = args[1];
+}
+
+function f() {
+ h(arguments);
+}
+
+for (var i = 0; i < 10000; ++i) {
+ f(100, 51);
+}
+
+appendToActual(g);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args5.js b/js/src/jit-test/tests/arguments/args5.js
new file mode 100644
index 0000000000..8bd1c1cb46
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args5.js
@@ -0,0 +1,24 @@
+actual = '';
+expected = '150,';
+
+var g = 0;
+
+function h(args) {
+ var ans = 0;
+ for (var i = 0; i < 5; ++i) {
+ ans += args[i];
+ }
+ g = ans;
+}
+
+function f() {
+ h(arguments);
+}
+
+for (var i = 0; i < 5; ++i) {
+ f(10, 20, 30, 40, 50);
+}
+appendToActual(g);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args6.js b/js/src/jit-test/tests/arguments/args6.js
new file mode 100644
index 0000000000..a2fc60d36a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args6.js
@@ -0,0 +1,22 @@
+actual = '';
+expected = '6,';
+
+// tracing length
+
+var g = 0;
+
+function h(args) {
+ g = args.length;
+}
+
+function f() {
+ h(arguments);
+}
+
+for (var i = 0; i < 5; ++i) {
+ f(10, 20, 30, 40, 50, 60);
+}
+appendToActual(g);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args6a.js b/js/src/jit-test/tests/arguments/args6a.js
new file mode 100644
index 0000000000..ce5206da1c
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args6a.js
@@ -0,0 +1,23 @@
+actual = '';
+expected = '5,';
+
+// tracing length
+
+var g = 0;
+
+function h(args) {
+ for (var i = 0; i < 6; ++i)
+ g = args.length;
+}
+
+function f() {
+ h(arguments);
+}
+
+for (var i = 0; i < 5; ++i) {
+ f(10, 20, 30, 40, 50);
+}
+appendToActual(g);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args7.js b/js/src/jit-test/tests/arguments/args7.js
new file mode 100644
index 0000000000..5d713e81ac
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args7.js
@@ -0,0 +1,14 @@
+actual = '';
+expected = '5,4,3,2,1,';
+
+function f() {
+ while (arguments.length > 0) {
+ appendToActual(arguments[arguments.length-1]);
+ arguments.length--;
+ }
+}
+
+f(1, 2, 3, 4, 5);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args8.js b/js/src/jit-test/tests/arguments/args8.js
new file mode 100644
index 0000000000..57938d9e23
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args8.js
@@ -0,0 +1,14 @@
+actual = '';
+expected = '[object Arguments],[object Arguments],[object Arguments],[object Arguments],[object Arguments],';
+
+function h() {
+ return arguments;
+}
+
+for (var i = 0; i < 5; ++i) {
+ var p = h(i, i*2);
+ appendToActual(p);
+}
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/args9.js b/js/src/jit-test/tests/arguments/args9.js
new file mode 100644
index 0000000000..79a54dfaef
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/args9.js
@@ -0,0 +1,16 @@
+actual = '';
+expected = '10,20,';
+
+function h() {
+ var p;
+ for (var i = 0; i < 5; ++i) {
+ p = arguments;
+ }
+ appendToActual(p[0]);
+ appendToActual(p[1]);
+}
+
+h(10, 20);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/argsub.js b/js/src/jit-test/tests/arguments/argsub.js
new file mode 100644
index 0000000000..e52992c6b5
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/argsub.js
@@ -0,0 +1,13 @@
+actual = '';
+expected = 'undefined,undefined,undefined,undefined,undefined,';
+
+function h() {
+ for (var i = 0; i < 5; ++i) {
+ appendToActual(arguments[100]);
+ }
+}
+
+h();
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/argsx-1.js b/js/src/jit-test/tests/arguments/argsx-1.js
new file mode 100644
index 0000000000..ea9d0906e4
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/argsx-1.js
@@ -0,0 +1,22 @@
+actual = '';
+expected = "function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,"
+
+// args object created by interpreter
+
+function f() {
+ var a = arguments;
+
+ for (var i = 0; i < 10; ++i) {
+ appendToActual(a.callee);
+ appendToActual(a.length);
+ appendToActual(a[0]);
+ appendToActual(a[1]);
+ }
+}
+
+f(1, 2, 3);
+f({}, 'a');
+f('abc', 'def');
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/argsx-2.js b/js/src/jit-test/tests/arguments/argsx-2.js
new file mode 100644
index 0000000000..5fe9af97d8
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/argsx-2.js
@@ -0,0 +1,23 @@
+actual = '';
+expected = "function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,"
+
+// args object created on trace
+
+function f() {
+ var a = arguments;
+
+ appendToActual(a.callee);
+ appendToActual(a.length);
+ appendToActual(a[0]);
+ appendToActual(a[1]);
+}
+
+for (var i = 0; i < 10; ++i)
+ f(1, 2, 3);
+for (var i = 0; i < 10; ++i)
+ f({}, 'a');
+for (var i = 0; i < 10; ++i)
+ f('abc', 'def');
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/argsx-3.js b/js/src/jit-test/tests/arguments/argsx-3.js
new file mode 100644
index 0000000000..ad5942c618
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/argsx-3.js
@@ -0,0 +1,27 @@
+actual = '';
+expected = "true,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,"
+
+// args object created by interpreter at record time, but not always at run time.
+
+function f(t) {
+ if (t) {
+ var b = arguments;
+ appendToActual(b[0]);
+ }
+
+ for (var i = 0; i < 10; ++i) {
+ var a = arguments;
+ appendToActual(a.callee);
+ appendToActual(a.length);
+ appendToActual(a[0]);
+ appendToActual(a[1]);
+ }
+}
+
+f(true, 1, 2, 3);
+f(false, 1, 2, 3);
+f(false, {}, 'a');
+f(false, 'abc', 'def');
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/argsx-3a.js b/js/src/jit-test/tests/arguments/argsx-3a.js
new file mode 100644
index 0000000000..fd278c039b
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/argsx-3a.js
@@ -0,0 +1,27 @@
+actual = '';
+expected = "function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,true,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,true,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],true,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,"
+
+// args object not created by interpreter at record time, but maybe at run time
+
+function f(t) {
+ if (t) {
+ var b = arguments;
+ appendToActual(b[0]);
+ }
+
+ for (var i = 0; i < 10; ++i) {
+ var a = arguments;
+ appendToActual(a.callee);
+ appendToActual(a.length);
+ appendToActual(a[0]);
+ appendToActual(a[1]);
+ }
+}
+
+f(false, 1, 2, 3);
+f(true, 1, 2, 3);
+f(true, {}, 'a');
+f(true, 'abc', 'def');
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/argsx-4.js b/js/src/jit-test/tests/arguments/argsx-4.js
new file mode 100644
index 0000000000..b52b14853c
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/argsx-4.js
@@ -0,0 +1,23 @@
+actual = '';
+expected = '[object Arguments] undefined undefined,[object Arguments] undefined undefined,';
+
+function f() {
+ g(arguments);
+}
+
+function g(a, b, c) {
+ h(arguments);
+ a = 1;
+ b = 2;
+ c = 3;
+ h(arguments);
+}
+
+function h(a, b, c) {
+ appendToActual(a + ' ' + b + ' ' + c);
+}
+
+f(4, 5, 6);
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/arguments-on-proto.js b/js/src/jit-test/tests/arguments/arguments-on-proto.js
new file mode 100644
index 0000000000..745c77b9da
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/arguments-on-proto.js
@@ -0,0 +1,27 @@
+function create() {
+ return Object.create(arguments, {2: {value: "shadowed"}});
+}
+
+function createStrict() {
+ "use strict";
+ return Object.create(arguments, {40: {value: "shadowed2"}});
+}
+
+function f() {
+ var args = [createStrict(10, 20, 30, 40), create(1, 2, 3)];
+
+ var threshold = getJitCompilerOptions()["ion.warmup.trigger"] + 101;
+
+ for (var i = 0; i < threshold; i++) {
+ // We switch between different arguments objects, to make
+ // sure the right IC is triggered.
+ var a = args[i % 2];
+ assertEq(a.length, (i % 2) ? 3 : 4);
+ assertEq(a[0], (i % 2) ? 1 : 10);
+ assertEq(a[1], (i % 2) ? 2 : 20);
+ assertEq(a[2], (i % 2) ? "shadowed" : 30);
+ assertEq(a[3], (i % 2) ? undefined : 40);
+ }
+}
+
+f();
diff --git a/js/src/jit-test/tests/arguments/bug-917585-relax-aliasing-constraints.js b/js/src/jit-test/tests/arguments/bug-917585-relax-aliasing-constraints.js
new file mode 100644
index 0000000000..03f77d7a7f
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug-917585-relax-aliasing-constraints.js
@@ -0,0 +1,18 @@
+
+function foo(a, b) {
+ blah(function (x) { a = x; }, b);
+ return arguments[0];
+}
+
+function blah(f, b) {
+ f(b);
+}
+
+function main() {
+ for (var i = 0; i < 1500; i++) {
+ var x = foo(i, i*2);
+ assertEq(x, i*2);
+ }
+}
+
+main();
diff --git a/js/src/jit-test/tests/arguments/bug1051760.js b/js/src/jit-test/tests/arguments/bug1051760.js
new file mode 100644
index 0000000000..aeb54feecc
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1051760.js
@@ -0,0 +1,4 @@
+function test() {
+ eval("var { [arguments] : y } = {};");
+}
+test();
diff --git a/js/src/jit-test/tests/arguments/bug1227287.js b/js/src/jit-test/tests/arguments/bug1227287.js
new file mode 100644
index 0000000000..d0c6b88262
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1227287.js
@@ -0,0 +1,8 @@
+// Note: Ion/Warp have known issues with function.arguments. See bug 1626294.
+
+function f(y) {
+ y = 1;
+ assertEq(arguments.callee.arguments[0], 1);
+ return () => y;
+}
+f(0);
diff --git a/js/src/jit-test/tests/arguments/bug1423937.js b/js/src/jit-test/tests/arguments/bug1423937.js
new file mode 100644
index 0000000000..ea4d4890a0
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1423937.js
@@ -0,0 +1,16 @@
+// |jit-test| exitstatus: 6; skip-if: getBuildConfiguration('pbl')
+var global = 0;
+setInterruptCallback(function() {
+ foo("A");
+});
+function foo(x) {
+ for (var i = 0; i < 1000; i++) {
+ var stack = getBacktrace({args: true});
+ }
+ if (global > 2) return;
+ global++;
+ interruptIf(true);
+ foo("B");
+ (function() { g = x;});
+}
+foo("C");
diff --git a/js/src/jit-test/tests/arguments/bug1503071.js b/js/src/jit-test/tests/arguments/bug1503071.js
new file mode 100644
index 0000000000..d2beeca982
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1503071.js
@@ -0,0 +1,16 @@
+// |jit-test| exitstatus: 6; skip-if: getBuildConfiguration('pbl')
+var g = true
+
+setInterruptCallback(function() {
+ print(getBacktrace({args: true}));
+});
+
+function foo(bt, x=3, y = eval("g")) {
+ if (g) {
+ g = false
+ interruptIf(true);
+ foo(false);
+ }
+ (function() { n = bt;});
+}
+foo(false);
diff --git a/js/src/jit-test/tests/arguments/bug1621265.js b/js/src/jit-test/tests/arguments/bug1621265.js
new file mode 100644
index 0000000000..8eaf37c480
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1621265.js
@@ -0,0 +1,17 @@
+// |jit-test| error:null
+
+function f(a) {
+ // Add |arguments[0]| to mark the function as having an arguments
+ // access. Even though there's a |JSOp::SetArg| bytecode is present, we can
+ // still use lazy arguments here, because the |JSOp::SetArg| bytecode is
+ // always unreachable.
+ var v = arguments[0];
+ assertEq(v, 1);
+
+ // Anything below the |throw| is unreachable.
+ throw null;
+
+ // Add an unreachable |JSOp::SetArg| bytecode.
+ a = 4;
+}
+f(1);
diff --git a/js/src/jit-test/tests/arguments/bug1692833.js b/js/src/jit-test/tests/arguments/bug1692833.js
new file mode 100644
index 0000000000..a7c7523eed
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1692833.js
@@ -0,0 +1,25 @@
+// |jit-test| skip-if: getBuildConfiguration('pbl')
+g13 = newGlobal({newCompartment: true})
+g13.parent = this;
+g13.eval("(" + function() {
+ Debugger(parent).onExceptionUnwind = function(frame) {
+ frame.older;
+ }
+} + ")()");
+
+function foo(depth) {
+ try {
+ if (depth > 0) {
+ bar(depth - arguments.length);
+ } else {
+ throw 1;
+ }
+ } catch (e) { throw e }
+}
+function bar(depth) {
+ foo(depth);
+}
+
+try {
+ foo(50);
+} catch {}
diff --git a/js/src/jit-test/tests/arguments/bug1696181.js b/js/src/jit-test/tests/arguments/bug1696181.js
new file mode 100644
index 0000000000..816a8c00e3
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1696181.js
@@ -0,0 +1,15 @@
+function b() {}
+function c() {}
+
+function foo() {
+ for (f of [b,c]) {
+ (function () {
+ f.apply({}, arguments);
+ })(1,2,3,4)
+ }
+}
+
+with({}) {}
+for (var i = 0; i < 100; i++) {
+ foo();
+}
diff --git a/js/src/jit-test/tests/arguments/bug1711414.js b/js/src/jit-test/tests/arguments/bug1711414.js
new file mode 100644
index 0000000000..174a78b507
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1711414.js
@@ -0,0 +1,11 @@
+function bar() { this[0] = "overwritten"; }
+
+function foo() {
+ bar.apply(arguments, arguments);
+ return arguments[0];
+}
+
+with ({}) {}
+for (var i = 0; i < 100; i++) {
+ assertEq(foo("original"), "overwritten");
+}
diff --git a/js/src/jit-test/tests/arguments/bug1749460.js b/js/src/jit-test/tests/arguments/bug1749460.js
new file mode 100644
index 0000000000..e78cf43f22
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1749460.js
@@ -0,0 +1,14 @@
+function opaque(x) {
+ with ({}) {}
+ return x;
+}
+
+function foo() {
+ "use strict";
+ Object.defineProperty(arguments, 0, {value: 1});
+ return opaque(...arguments);
+}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(foo(0), 1);
+}
diff --git a/js/src/jit-test/tests/arguments/bug1762575-1.js b/js/src/jit-test/tests/arguments/bug1762575-1.js
new file mode 100644
index 0000000000..b4b15ddf98
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1762575-1.js
@@ -0,0 +1,44 @@
+// Tests on mapped arguments objects.
+
+function ArraySlice() {
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.slice.call(arguments);
+ assertEq(result[0], 1);
+}
+ArraySlice(0);
+
+function ArrayShift() {
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.shift.call(arguments);
+ assertEq(result, 1);
+}
+ArrayShift(0);
+
+function ArrayPop() {
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.pop.call(arguments);
+ assertEq(result, 1);
+}
+ArrayPop(0);
+
+function ArrayJoin() {
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.join.call(arguments);
+ assertEq(result, "1");
+}
+ArrayJoin(0);
+
+function ArrayIncludes() {
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.includes.call(arguments, 1);
+ assertEq(result, true);
+}
+ArrayIncludes(0);
+
+function FunctionApply() {
+ Object.defineProperty(arguments, 0, {value: 1});
+ var id = x => x;
+ var result = id.apply(null, arguments);
+ assertEq(result, 1);
+}
+FunctionApply(0);
diff --git a/js/src/jit-test/tests/arguments/bug1762575-2.js b/js/src/jit-test/tests/arguments/bug1762575-2.js
new file mode 100644
index 0000000000..683e5420ae
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1762575-2.js
@@ -0,0 +1,50 @@
+// Tests on unmapped arguments objects.
+
+function ArraySlice() {
+ "use strict";
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.slice.call(arguments);
+ assertEq(result[0], 1);
+}
+ArraySlice(0);
+
+function ArrayShift() {
+ "use strict";
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.shift.call(arguments);
+ assertEq(result, 1);
+}
+ArrayShift(0);
+
+function ArrayPop() {
+ "use strict";
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.pop.call(arguments);
+ assertEq(result, 1);
+}
+ArrayPop(0);
+
+function ArrayJoin() {
+ "use strict";
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.join.call(arguments);
+ assertEq(result, "1");
+}
+ArrayJoin(0);
+
+function ArrayIncludes() {
+ "use strict";
+ Object.defineProperty(arguments, 0, {value: 1});
+ var result = Array.prototype.includes.call(arguments, 1);
+ assertEq(result, true);
+}
+ArrayIncludes(0);
+
+function FunctionApply() {
+ "use strict";
+ Object.defineProperty(arguments, 0, {value: 1});
+ var id = x => x;
+ var result = id.apply(null, arguments);
+ assertEq(result, 1);
+}
+FunctionApply(0);
diff --git a/js/src/jit-test/tests/arguments/bug1762575-3.js b/js/src/jit-test/tests/arguments/bug1762575-3.js
new file mode 100644
index 0000000000..371eab009f
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1762575-3.js
@@ -0,0 +1,89 @@
+// Test implementation details when arguments object keep strong references
+// to their elements.
+
+function checkWeakRef(f, isCleared = true) {
+ let [wr, args] = f({});
+
+ assertEq(wr.deref() !== undefined, true);
+
+ clearKeptObjects();
+ gc();
+
+ // In an ideal world, the reference is always cleared. But in specific
+ // circumstances we're currently keeping the reference alive. Should this
+ // ever change, feel free to update this test case accordingly. IOW having
+ // |isCleared == false| is okay for spec correctness, but it isn't optimal.
+ assertEq(wr.deref() === undefined, isCleared);
+}
+
+checkWeakRef(function() {
+ // Create a weak-ref for the first argument.
+ let wr = new WeakRef(arguments[0]);
+
+ // Clear the reference from the arguments object.
+ arguments[0] = null;
+
+ // Let the arguments object escape.
+ return [wr, arguments];
+});
+
+checkWeakRef(function() {
+ // Create a weak-ref for the first argument.
+ let wr = new WeakRef(arguments[0]);
+
+ // Clear the reference from the arguments object.
+ Object.defineProperty(arguments, 0, {value: null});
+
+ // Let the arguments object escape.
+ return [wr, arguments];
+});
+
+checkWeakRef(function self() {
+ // Create a weak-ref for the first argument.
+ let wr = new WeakRef(arguments[0]);
+
+ // Delete operation doesn't clear the reference!
+ delete arguments[0];
+
+ // Let the arguments object escape.
+ return [wr, arguments];
+}, /*isCleared=*/ false);
+
+checkWeakRef(function() {
+ "use strict";
+
+ // Create a weak-ref for the first argument.
+ let wr = new WeakRef(arguments[0]);
+
+ // Clear the reference from the arguments object.
+ arguments[0] = null;
+
+ // Let the arguments object escape.
+ return [wr, arguments];
+});
+
+checkWeakRef(function() {
+ "use strict";
+
+ // Create a weak-ref for the first argument.
+ let wr = new WeakRef(arguments[0]);
+
+ // This define operation doesn't clear the reference!
+ Object.defineProperty(arguments, 0, {value: null});
+
+ // Let the arguments object escape.
+ return [wr, arguments];
+}, /*isCleared=*/ false);
+
+checkWeakRef(function() {
+ "use strict";
+
+ // Create a weak-ref for the first argument.
+ let wr = new WeakRef(arguments[0]);
+
+ // Delete operation doesn't clear the reference!
+ delete arguments[0];
+
+ // Let the arguments object escape.
+ return [wr, arguments];
+}, /*isCleared=*/ false);
diff --git a/js/src/jit-test/tests/arguments/bug1825907.js b/js/src/jit-test/tests/arguments/bug1825907.js
new file mode 100644
index 0000000000..5e9be25d2f
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1825907.js
@@ -0,0 +1,7 @@
+function f(arg) {
+ eval(`var y = 1; function f() {return y}; f();`);
+ delete y;
+ arguments[0] = 5;
+ assertEq(arg, 5);
+}
+f(0);
diff --git a/js/src/jit-test/tests/arguments/bug1827073.js b/js/src/jit-test/tests/arguments/bug1827073.js
new file mode 100644
index 0000000000..d87ec97b48
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug1827073.js
@@ -0,0 +1,15 @@
+// |jit-test| --fast-warmup
+let depth = 0;
+function f1(a2, a3, a4, a5) {
+ f2();
+}
+function f2() {
+ // Recursion depth reduced to allow PBL with debug build (hence larger
+ // frames) to work.
+ if (depth++ > 75) {
+ return;
+ }
+ f1(1, 2);
+ assertEq(JSON.stringify(Array.from(f1.arguments)), "[1,2]");
+}
+f1(1, 2);
diff --git a/js/src/jit-test/tests/arguments/bug503772.js b/js/src/jit-test/tests/arguments/bug503772.js
new file mode 100644
index 0000000000..6ef8e1f974
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug503772.js
@@ -0,0 +1,16 @@
+function f(a) {
+ // Create arguments on trace
+ var z = arguments;
+ // Make f need a call object
+ if (false) {
+ var p = function() { ++a; }
+ }
+}
+
+function g() {
+ for (var i = 0; i < 5; ++i) {
+ f(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
+ }
+}
+
+g();
diff --git a/js/src/jit-test/tests/arguments/bug508178.js b/js/src/jit-test/tests/arguments/bug508178.js
new file mode 100644
index 0000000000..c779c82200
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug508178.js
@@ -0,0 +1,18 @@
+actual = '';
+expected = 'g,g,g,g,f,';
+
+function test() {
+ var testargs = arguments;
+ var f = function (name, which) {
+ var args = [testargs, arguments];
+ return args[which][0];
+ };
+ var arr = [0, 0, 0, 0, 1];
+ for (var i = 0; i < arr.length; i++)
+ arr[i] = f("f", arr[i]);
+ appendToActual(arr);
+}
+test('g');
+
+
+assertEq(actual, expected)
diff --git a/js/src/jit-test/tests/arguments/bug633020.js b/js/src/jit-test/tests/arguments/bug633020.js
new file mode 100644
index 0000000000..6e30bd1250
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug633020.js
@@ -0,0 +1,11 @@
+var N = 10;
+function f(b) {
+ var a = [];
+ for (var i = 0; i < N; i++)
+ a[i] = {};
+ a[N-1] = arguments;
+ for (var i = 0; i < N; i++)
+ a[i][0] = i;
+ assertEq(b, N - 1);
+}
+f(null);
diff --git a/js/src/jit-test/tests/arguments/bug843985.js b/js/src/jit-test/tests/arguments/bug843985.js
new file mode 100644
index 0000000000..3365b9ec87
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug843985.js
@@ -0,0 +1,5 @@
+
+for (x in (function*() {
+ eval("arguments[0]");
+ yield;
+})())(function() {})
diff --git a/js/src/jit-test/tests/arguments/bug956173.js b/js/src/jit-test/tests/arguments/bug956173.js
new file mode 100644
index 0000000000..d88efaa7ab
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/bug956173.js
@@ -0,0 +1,7 @@
+function foo() {
+ {
+ let x=arguments;
+ return function() { return x; };
+ }
+}
+foo()();
diff --git a/js/src/jit-test/tests/arguments/defaults-basic.js b/js/src/jit-test/tests/arguments/defaults-basic.js
new file mode 100644
index 0000000000..bca8528581
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-basic.js
@@ -0,0 +1,35 @@
+function f1(a, bIs, b=3) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+}
+assertEq(f1.length, 2);
+f1(1, 3);
+f1(1, 42, 42);
+f1(1, 3, undefined);
+function f2(a, bIs, cIs, b=3, c=4) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+ assertEq(c, cIs);
+}
+assertEq(f2.length, 3);
+f2(1, 3, 4);
+f2(1, 42, 4, 42);
+f2(1, 42, 43, 42, 43);
+f2(1, 3, 4, undefined);
+f2(1, 42, 4, 42, undefined);
+f2(1, 3, 42, undefined, 42);
+function f3(a, b, c=4) {
+ assertEq(a, 1);
+ assertEq(b, undefined);
+ assertEq(c, 4);
+}
+f3(1);
+function f4(a, bIs, cIs, b=3, c) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+ assertEq(c, cIs);
+}
+assertEq(f4.length, 3);
+f4(1, 3, undefined);
+f4(1, 4, undefined, 4);
+f4(1, 4, 5, 4, 5);
diff --git a/js/src/jit-test/tests/arguments/defaults-bound-to-function.js b/js/src/jit-test/tests/arguments/defaults-bound-to-function.js
new file mode 100644
index 0000000000..28a1c3b455
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-bound-to-function.js
@@ -0,0 +1,43 @@
+load(libdir + "asserts.js");
+
+function f(a=42) {
+ return a;
+ function a() { return 19; }
+}
+assertEq(f()(), 19);
+function h(a=b, b=43) {
+ return [a, b];
+ function b() { return 42; }
+}
+// TDZ
+assertThrowsInstanceOf(h, ReferenceError);
+function i(b=FAIL) {
+ function b() {}
+}
+assertThrowsInstanceOf(i, ReferenceError);
+i(42);
+function j(a=(b=42), b=8) {
+ return b;
+ function b() { return 43; }
+}
+// TDZ
+assertThrowsInstanceOf(j, ReferenceError);
+function k(a=(b=42), b=8) {
+ return b;
+ function a() { return 43; }
+}
+// TDZ
+assertThrowsInstanceOf(k, ReferenceError);
+function l(a=8, b=a) {
+ return b;
+ function a() { return 42; }
+}
+assertEq(l(), 8);
+function m([a, b]=[1, 2], c=a) {
+ function a() { return 42; }
+ assertEq(typeof a, "function");
+ assertEq(a(), 42);
+ assertEq(b, 2);
+ assertEq(c, 1);
+}
+m();
diff --git a/js/src/jit-test/tests/arguments/defaults-bug759904.js b/js/src/jit-test/tests/arguments/defaults-bug759904.js
new file mode 100644
index 0000000000..f1ea39208a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-bug759904.js
@@ -0,0 +1,4 @@
+function* a(b=3) {
+ yield
+}
+a()
diff --git a/js/src/jit-test/tests/arguments/defaults-call-function.js b/js/src/jit-test/tests/arguments/defaults-call-function.js
new file mode 100644
index 0000000000..d3dcda0865
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-call-function.js
@@ -0,0 +1,15 @@
+load(libdir + "asserts.js");
+
+function f1(a=g()) {
+ function g() {
+ }
+}
+assertThrowsInstanceOf(f1, ReferenceError);
+
+function f2(a=g()) {
+ function g() {
+ return 43;
+ }
+ assertEq(a, 42);
+}
+f2(42);
diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-array.js b/js/src/jit-test/tests/arguments/defaults-destructuring-array.js
new file mode 100644
index 0000000000..e3994a8795
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-destructuring-array.js
@@ -0,0 +1,17 @@
+function f1(a, bIs, [b]=[3]) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+}
+assertEq(f1.length, 2);
+f1(1, 3);
+f1(1, 42, [42]);
+f1(1, 3, undefined);
+
+function f2(a, bIs, [b]=[]) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+}
+assertEq(f2.length, 2);
+f2(1, undefined);
+f2(1, 42, [42]);
+f2(1, undefined, undefined);
diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js b/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js
new file mode 100644
index 0000000000..750289e44e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js
@@ -0,0 +1,19 @@
+function f1(a, bIs, cIs, dIs, {b}={b: 3}, c=4, [d]=[5]) {
+ assertEq(a, 1),
+ assertEq(b, bIs),
+ assertEq(c, cIs),
+ assertEq(d, dIs)
+}
+assertEq(f1.length, 4);
+f1(1, 3, 4, 5);
+f1(1, 42, 43, 44, {b: 42}, 43, [44]);
+
+let f2 = (a, bIs, cIs, dIs, {b}={b: 3}, c=4, [d]=[5]) => (
+ assertEq(a, 1),
+ assertEq(b, bIs),
+ assertEq(c, cIs),
+ assertEq(d, dIs)
+);
+assertEq(f2.length, 4);
+f2(1, 3, 4, 5);
+f2(1, 42, 43, 44, {b: 42}, 43, [44]);
diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-function-expression.js b/js/src/jit-test/tests/arguments/defaults-destructuring-function-expression.js
new file mode 100644
index 0000000000..9517a5c4d4
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-destructuring-function-expression.js
@@ -0,0 +1,9 @@
+let f = function(a, bIs, cIs, dIs, {b}={b: 3}, c=4, [d]=[5]) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+ assertEq(c, cIs);
+ assertEq(d, dIs);
+};
+assertEq(f.length, 4);
+f(1, 3, 4, 5);
+f(1, 42, 43, 44, {b: 42}, 43, [44]);
diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-mixed-default-value.js b/js/src/jit-test/tests/arguments/defaults-destructuring-mixed-default-value.js
new file mode 100644
index 0000000000..e54255579e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-destructuring-mixed-default-value.js
@@ -0,0 +1,55 @@
+function f1(a=1,
+ [b, c=(assertEq(a, 2), a=3, 42)]=[(assertEq(a, 1), a=2, 43)],
+ {d, e:e=(assertEq(a, 4), a=5, 44)}={d: (assertEq(a, 3), a=4, 45)},
+ f=(assertEq(a, 5), a=6, 46)) {
+ assertEq(a, 6);
+ assertEq(b, 43);
+ assertEq(c, 42);
+ assertEq(d, 45);
+ assertEq(e, 44);
+ assertEq(f, 46);
+}
+assertEq(f1.length, 0);
+f1();
+
+function f2(a=1,
+ [b, c=assertEq(false)]=[(assertEq(a, 1), a=2, 42), (assertEq(a, 2), a=3, 43)],
+ {d, e:e=assertEq(false)}={d: (assertEq(a, 3), a=4, 44), e: (assertEq(a, 4), a=5, 45)},
+ f=(assertEq(a, 5), a=6, 46)) {
+ assertEq(a, 6);
+ assertEq(b, 42);
+ assertEq(c, 43);
+ assertEq(d, 44);
+ assertEq(e, 45);
+ assertEq(f, 46);
+}
+assertEq(f2.length, 0);
+f2();
+
+function f3(a=1,
+ [b, c=(assertEq(a, 1), a=2, 42)]=[assertEq(false)],
+ {d, e:e=(assertEq(a, 2), a=3, 43)}={d: assertEq(false)},
+ f=(assertEq(a, 3), a=4, 44)) {
+ assertEq(a, 4);
+ assertEq(b, 8);
+ assertEq(c, 42);
+ assertEq(d, 9);
+ assertEq(e, 43);
+ assertEq(f, 44);
+}
+assertEq(f3.length, 0);
+f3(undefined, [8], {d: 9});
+
+function f4(a=1,
+ [b, c=assertEq(false)]=[assertEq(false), assertEq(false)],
+ {d, e:e=assertEq(false)}={d: assertEq(false), e: assertEq(false)},
+ f=(assertEq(a, 1), a=2, 42)) {
+ assertEq(a, 2);
+ assertEq(b, 8);
+ assertEq(c, 9);
+ assertEq(d, 10);
+ assertEq(e, 11);
+ assertEq(f, 42);
+}
+assertEq(f4.length, 0);
+f4(undefined, [8, 9], {d: 10, e: 11});
diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-mixed.js b/js/src/jit-test/tests/arguments/defaults-destructuring-mixed.js
new file mode 100644
index 0000000000..74cb00f1f2
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-destructuring-mixed.js
@@ -0,0 +1,29 @@
+function f1(a, bIs, cIs, dIs, b=3, {c}={c: 4}, [d]=[5]) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+ assertEq(c, cIs);
+ assertEq(d, dIs);
+}
+assertEq(f1.length, 4);
+f1(1, 3, 4, 5);
+f1(1, 42, 4, 5, 42);
+f1(1, 42, 43, 5, 42, {c: 43});
+f1(1, 42, 43, 44, 42, {c: 43}, [44]);
+f1(1, 3, 4, 5, undefined);
+f1(1, 42, 4, 5, 42, undefined);
+f1(1, 3, 42, 5, undefined, {c: 42});
+f1(1, 3, 4, 42, undefined, undefined, [42]);
+
+function f2(a, bIs, cIs, dIs, eIs, {b}={b: 3}, [c]=[b], d=c, {ee: e}={ee: d}) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+ assertEq(c, cIs);
+ assertEq(d, dIs);
+ assertEq(e, eIs);
+}
+assertEq(f2.length, 5);
+f2(1, 3, 3, 3, 3);
+f2(1, 42, 42, 42, 42, {b: 42});
+f2(1, 42, 43, 43, 43, {b: 42}, [43]);
+f2(1, 42, 43, 44, 44, {b: 42}, [43], 44);
+f2(1, 42, 43, 44, 45, {b: 42}, [43], 44, {ee: 45});
diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-object.js b/js/src/jit-test/tests/arguments/defaults-destructuring-object.js
new file mode 100644
index 0000000000..0ca970a144
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-destructuring-object.js
@@ -0,0 +1,27 @@
+function f1(a, bIs, cIs, {b}={b: 3}, {cc: c}={cc: 4}) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+ assertEq(c, cIs);
+}
+assertEq(f1.length, 3);
+f1(1, 3, 4);
+f1(1, 42, 4, {b: 42});
+f1(1, 42, 4, {b: 42}, undefined);
+f1(1, 42, 43, {b: 42}, {cc: 43});
+f1(1, 3, 4, undefined);
+f1(1, 3, 4, undefined, undefined);
+f1(1, 3, 43, undefined, {cc: 43});
+
+function f2(a, bIs, cIs, {b}={}, {cc: c}={}) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+ assertEq(c, cIs);
+}
+assertEq(f2.length, 3);
+f2(1, undefined, undefined);
+f2(1, 42, undefined, {b: 42});
+f2(1, 42, undefined, {b: 42}, undefined);
+f2(1, 42, 43, {b: 42}, {cc: 43});
+f2(1, undefined, undefined, undefined);
+f2(1, undefined, undefined, undefined, undefined);
+f2(1, undefined, 43, undefined, {cc: 43});
diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-with-rest.js b/js/src/jit-test/tests/arguments/defaults-destructuring-with-rest.js
new file mode 100644
index 0000000000..26c35f6a43
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-destructuring-with-rest.js
@@ -0,0 +1,29 @@
+load(libdir + "asserts.js");
+load(libdir + "eqArrayHelper.js");
+
+function f1(a, bIs, [b]=[3], ...rest) {
+ assertEq(a, 1);
+ assertEq(bIs, b);
+ assertEqArray(rest, []);
+}
+assertEq(f1.length, 2);
+f1(1, 3);
+f1(1, 42, [42]);
+
+function f2([a]=[rest], ...rest) {
+ assertEq(a, undefined);
+}
+// TDZ
+assertThrowsInstanceOf(f2, ReferenceError);
+
+function f3([a]=[rest], ...rest) {
+ assertEq(a, 1);
+ assertEqArray(rest, [2, 3, 4]);
+}
+// TDZ
+assertThrowsInstanceOf(f3, ReferenceError);
+
+function f4([a]=rest, ...rest) {
+}
+// TDZ
+assertThrowsInstanceOf(f4, ReferenceError);
diff --git a/js/src/jit-test/tests/arguments/defaults-evaluation-order.js b/js/src/jit-test/tests/arguments/defaults-evaluation-order.js
new file mode 100644
index 0000000000..c4ddff7372
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-evaluation-order.js
@@ -0,0 +1,27 @@
+function f1(a, bIs, cIs, dIs, b=a, c=5, d=c) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+ assertEq(c, cIs);
+ assertEq(d, dIs);
+}
+f1(1, 1, 5, 5);
+f1(1, 42, 5, 5, 42);
+f1(1, 42, 43, 43, 42, 43);
+f1(1, 42, 43, 44, 42, 43, 44);
+function f2(a=[]) { return a; }
+assertEq(f2() !== f2(), true);
+function f3(a=function () {}) { return a; }
+assertEq(f3() !== f3(), true);
+function f4(a=Date) { return a; }
+assertEq(f4(), Date);
+Date = 0;
+assertEq(f4(), 0);
+function f5(x=FAIL()) {}; // don't throw
+var n = 0;
+function f6(a=n++) {}
+assertEq(n, 0);
+function f7([a, b], A=a, B=b) {
+ assertEq(A, a);
+ assertEq(B, b);
+}
+f7([0, 1]);
diff --git a/js/src/jit-test/tests/arguments/defaults-exceptions.js b/js/src/jit-test/tests/arguments/defaults-exceptions.js
new file mode 100644
index 0000000000..ab8d9c1b69
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-exceptions.js
@@ -0,0 +1,6 @@
+load(libdir + "asserts.js");
+
+function die() { throw "x"; }
+var ok = true;
+function f(a = die()) { ok = false; }
+assertThrowsValue(f, "x");
diff --git a/js/src/jit-test/tests/arguments/defaults-invalid-syntax.js b/js/src/jit-test/tests/arguments/defaults-invalid-syntax.js
new file mode 100644
index 0000000000..f1e1e508af
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-invalid-syntax.js
@@ -0,0 +1,30 @@
+load(libdir + "asserts.js");
+
+assertThrowsInstanceOf(function () {
+ eval("function f(...rest=23) {}");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("function f(a=yield 24) {}");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("function f(a={a : 19 + (yield 24).prop}) {}");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("function f(a=1,a=1) {}");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("function f(a,a=1) {}");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("function f(a=1,a) {}");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("function f(a,a,b=1) {}");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("function f(a,b=1,a=1) {}");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("function f(a=1,b=1,a=1) {}");
+}, SyntaxError);
+function silly_but_okay(a=(function* () { yield 97; })) {}
diff --git a/js/src/jit-test/tests/arguments/defaults-scoping.js b/js/src/jit-test/tests/arguments/defaults-scoping.js
new file mode 100644
index 0000000000..366439590e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-scoping.js
@@ -0,0 +1,36 @@
+load(libdir + "asserts.js");
+
+var x = 'global';
+function f(a=x) { // global variable x
+ var x = 'local';
+ return a;
+}
+assertEq(f(), 'global');
+
+var i = 42;
+function g(f=function () { return ++i; }) { // closes on global variable i
+ var i = 0;
+ return f;
+}
+var gf = g();
+assertEq(gf(), 43);
+assertEq(gf(), 44);
+gf = g();
+assertEq(gf(), 45);
+
+function h(f=function (s) { return eval(s); }) { // closes on global scope
+ var x = 'hlocal';
+ return f;
+}
+var hf = h();
+assertEq(hf('x'), 'global');
+assertEq(hf('f'), hf);
+assertEq(hf('var x = 3; x'), 3);
+
+function j(expr, v=eval(expr)) {
+ return v;
+}
+assertEq(j("expr"), "expr");
+assertThrowsInstanceOf(() => j("v"), ReferenceError);
+assertEq(j("Array"), Array);
+assertEq(j("arguments").length, 1);
diff --git a/js/src/jit-test/tests/arguments/defaults-strict-mode.js b/js/src/jit-test/tests/arguments/defaults-strict-mode.js
new file mode 100644
index 0000000000..c4ba7bd63d
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-strict-mode.js
@@ -0,0 +1,41 @@
+load(libdir + "asserts.js");
+
+eval(`"use strict";
+function f1(f=(function () { return typeof this !== "object"; })) { return f; }
+assertEq(f1()(), true);
+`);
+
+function f2(f=(function () { "use strict"; return (function () { return typeof this !== "object"; }) })) { assertEq(typeof this, "object"); return f; }
+assertEq(f2()()(), true);
+
+eval(`"use strict";
+function f3(f=(function () { return (function () { return typeof this !== "object"; }) })) { return f; }
+assertEq(f3()()(), true);
+`);
+
+// These should be okay.
+function f4(f=(function () { with (Object) {} }), g=(function () { "use strict"; })) {}
+function f5(g=(function () { "use strict"; }), f=(function () { with (Object) {} })) {}
+
+assertThrowsInstanceOf(function () {
+ eval("'use strict'; function f(a=delete x) { }");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ Math.sin(4);
+ eval("'use strict'; function f(a='\\251') { }");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("'use strict'; function f(a='\\251', b=delete x) { }");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("'use strict'; function f(a=delete x, b='\\251') { }");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("'use strict'; function f(a=(function () { '\\251'; })) { }");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("'use strict'; function f(a=(function () { with (Object) {} })) { }");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("'use strict'; function f(a=(function (b, b) {})) { }");
+}, SyntaxError);
diff --git a/js/src/jit-test/tests/arguments/defaults-with-arguments.js b/js/src/jit-test/tests/arguments/defaults-with-arguments.js
new file mode 100644
index 0000000000..9924c7c238
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-with-arguments.js
@@ -0,0 +1,10 @@
+function f(a=1, b=2, c=3) { return arguments; }
+var args = f();
+assertEq(args.length, 0);
+assertEq("0" in args, false);
+args = f(5, 6);
+assertEq(args.length, 2);
+assertEq(args[1], 6);
+args = f(9, 8, 7, 6, 5);
+assertEq(args.length, 5);
+assertEq(args[4], 5);
diff --git a/js/src/jit-test/tests/arguments/defaults-with-rest.js b/js/src/jit-test/tests/arguments/defaults-with-rest.js
new file mode 100644
index 0000000000..b0c7c8bcf9
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/defaults-with-rest.js
@@ -0,0 +1,23 @@
+load(libdir + "eqArrayHelper.js");
+load(libdir + "asserts.js");
+
+function f1(a, bIs, b=3, ...rest) {
+ assertEq(a, 1);
+ assertEq(bIs, b);
+ assertEqArray(rest, []);
+}
+assertEq(f1.length, 2);
+f1(1, 3);
+f1(1, 42, 42);
+function f2(a=rest, ...rest) {
+}
+// TDZ
+assertThrowsInstanceOf(f2, ReferenceError);
+function f3(a=rest, ...rest) {
+}
+assertThrowsInstanceOf(f3, ReferenceError);
+function f4(a=42, ...f) {
+ assertEq(typeof f, "function");
+ function f() {}
+}
+f4()
diff --git a/js/src/jit-test/tests/arguments/destructuring-after-defaults.js b/js/src/jit-test/tests/arguments/destructuring-after-defaults.js
new file mode 100644
index 0000000000..66f24a8342
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/destructuring-after-defaults.js
@@ -0,0 +1,14 @@
+load(libdir + "asserts.js");
+
+function f1(a, bIs, cIs, dIs, b=1, [c], {d}) {
+ assertEq(a, 1);
+ assertEq(b, bIs);
+ assertEq(c, cIs);
+ assertEq(d, dIs);
+}
+assertEq(f1.length, 4);
+f1(1, 1, 42, 43, undefined, [42], {d: 43});
+f1(1, 42, 43, 44, 42, [43], {d: 44});
+assertThrowsInstanceOf(function () {
+ f1(1, 1, 1, 1);
+}, TypeError);
diff --git a/js/src/jit-test/tests/arguments/destructuring-default-value-scope.js b/js/src/jit-test/tests/arguments/destructuring-default-value-scope.js
new file mode 100644
index 0000000000..c4b16ea4df
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/destructuring-default-value-scope.js
@@ -0,0 +1,10 @@
+var a = 10;
+function f1(a,
+ [b=(assertEq(a, 1), a=2, 42)],
+ {c:c=(assertEq(a, 2), a=3, 43)}) {
+ assertEq(a, 3);
+ assertEq(b, 42);
+ assertEq(c, 43);
+}
+f1(1, [], {});
+assertEq(a, 10);
diff --git a/js/src/jit-test/tests/arguments/destructuring-exprbody.js b/js/src/jit-test/tests/arguments/destructuring-exprbody.js
new file mode 100644
index 0000000000..5f3f04ecb7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/destructuring-exprbody.js
@@ -0,0 +1,8 @@
+// See bug 763313
+load(libdir + "iteration.js");
+function f([a]) { return a; }
+var i = 0;
+var o = {[Symbol.iterator]: function () { i++; return {
+ next: function () { i++; return {value: 42, done: false}; }}}};
+assertEq(f(o), 42);
+assertEq(i, 2);
diff --git a/js/src/jit-test/tests/arguments/destructuring-with-rest.js b/js/src/jit-test/tests/arguments/destructuring-with-rest.js
new file mode 100644
index 0000000000..81e69ce54d
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/destructuring-with-rest.js
@@ -0,0 +1,21 @@
+load(libdir + "eqArrayHelper.js");
+
+function f1(a, bIs, [b], ...rest) {
+ assertEq(a, 1);
+ assertEq(bIs, b);
+ assertEqArray(rest, []);
+}
+assertEq(f1.length, 3);
+f1(1, 3, [3]);
+f1(1, 42, [42]);
+
+function f2([a], ...rest) {
+ assertEq(a, undefined);
+}
+f2([]);
+
+function f3([a], ...rest) {
+ assertEq(a, 1);
+ assertEqArray(rest, [2, 3, 4]);
+}
+f3([1], 2, 3, 4);
diff --git a/js/src/jit-test/tests/arguments/dynamicBindings.js b/js/src/jit-test/tests/arguments/dynamicBindings.js
new file mode 100644
index 0000000000..326038e12b
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/dynamicBindings.js
@@ -0,0 +1,32 @@
+
+function testEval(x, y) {
+ x = 5;
+ eval("arguments[0] += 10");
+ assertEq(x, 15);
+}
+for (var i = 0; i < 5; i++)
+ testEval(3);
+
+function testEvalWithArguments(x, y) {
+ eval("arguments[0] += 10");
+ assertEq(arguments[y], 13);
+}
+for (var i = 0; i < 5; i++)
+ testEvalWithArguments(3, 0);
+
+function testNestedEval(x, y) {
+ x = 5;
+ eval("eval('arguments[0] += 10')");
+ assertEq(x, 15);
+}
+for (var i = 0; i < 5; i++)
+ testNestedEval(3);
+
+function testWith(x, y) {
+ with ({}) {
+ arguments[0] += 10;
+ assertEq(x, 13);
+ }
+}
+for (var i = 0; i < 5; i++)
+ testWith(3);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-apply-forwarded.js b/js/src/jit-test/tests/arguments/external-arguments-apply-forwarded.js
new file mode 100644
index 0000000000..b2f388dd7e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-apply-forwarded.js
@@ -0,0 +1,18 @@
+function foo(x,y) {
+ function capture() { return x; }
+ return bar(arguments);
+}
+
+function bar(x) {
+ return baz.apply({}, x) + arguments.length;
+}
+
+function baz(x,y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-apply.js b/js/src/jit-test/tests/arguments/external-arguments-apply.js
new file mode 100644
index 0000000000..997aafa2d2
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-apply.js
@@ -0,0 +1,17 @@
+function foo(x,y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ return baz.apply({}, x) + arguments.length;
+}
+
+function baz(x,y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-callee.js b/js/src/jit-test/tests/arguments/external-arguments-callee.js
new file mode 100644
index 0000000000..cee9edba51
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-callee.js
@@ -0,0 +1,13 @@
+function foo() {
+ with ({}) {}
+ return bar(arguments);
+}
+
+function bar(x) {
+ assertEq(x.callee.name, "foo");
+ assertEq(arguments.callee.name, "bar");
+}
+
+for (var i = 0; i < 100; i++) {
+ foo();
+}
diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists-oob.js b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists-oob.js
new file mode 100644
index 0000000000..d6ff36060e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists-oob.js
@@ -0,0 +1,14 @@
+function foo(x,y) {
+ delete arguments[1];
+ return bar(arguments);
+}
+
+function bar(x) {
+ return (100 in x) + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 100);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists.js b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists.js
new file mode 100644
index 0000000000..a65abe83e5
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists.js
@@ -0,0 +1,14 @@
+function foo(x,y) {
+ delete arguments[1];
+ return bar(arguments);
+}
+
+function bar(x) {
+ return (1 in x) + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 100);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-deleted-oob.js b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-oob.js
new file mode 100644
index 0000000000..8a38aaa8d6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-oob.js
@@ -0,0 +1,14 @@
+function foo(x,y) {
+ delete arguments[0];
+ return bar(arguments);
+}
+
+function bar(x) {
+ return (x[100]|0) + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 100);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-deleted.js b/js/src/jit-test/tests/arguments/external-arguments-element-deleted.js
new file mode 100644
index 0000000000..f1ba46818a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-element-deleted.js
@@ -0,0 +1,14 @@
+function foo(x,y) {
+ delete arguments[0];
+ return bar(arguments);
+}
+
+function bar(x) {
+ return x[1] + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-exists-oob.js b/js/src/jit-test/tests/arguments/external-arguments-element-exists-oob.js
new file mode 100644
index 0000000000..2af2140f37
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-element-exists-oob.js
@@ -0,0 +1,13 @@
+function foo(x,y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ return (100 in x) + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 100);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-exists.js b/js/src/jit-test/tests/arguments/external-arguments-element-exists.js
new file mode 100644
index 0000000000..f8e8aadd7c
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-element-exists.js
@@ -0,0 +1,13 @@
+function foo(x,y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ return (1 in x) + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 200);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-oob.js b/js/src/jit-test/tests/arguments/external-arguments-element-oob.js
new file mode 100644
index 0000000000..452f08768d
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-element-oob.js
@@ -0,0 +1,13 @@
+function foo(x,y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ return (x[100]|0) + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 100);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-element.js b/js/src/jit-test/tests/arguments/external-arguments-element.js
new file mode 100644
index 0000000000..644eecec82
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-element.js
@@ -0,0 +1,13 @@
+function foo(x,y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ return x[1] + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-apply.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-apply.js
new file mode 100644
index 0000000000..882476bf0a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-apply.js
@@ -0,0 +1,14 @@
+function foo() {
+ return bar(arguments);
+}
+function bar(argsFromFoo) {
+ return baz.apply({}, argsFromFoo)
+}
+function baz(a,b) { return a + b; }
+
+var sum = 0;
+with ({}) {}
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-1.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-1.js
new file mode 100644
index 0000000000..ad42ff1be8
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-1.js
@@ -0,0 +1,15 @@
+function foo() {
+ return bar(arguments);
+}
+function bar(argsFromFoo) {
+ var args = Array.prototype.slice.call(argsFromFoo);
+ return baz(args[0], args[1]);
+}
+function baz(a,b) { return a + b; }
+
+var sum = 0;
+with ({}) {}
+for (var i = 0; i < 100; i++) {
+ sum += foo(1, 2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-2.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-2.js
new file mode 100644
index 0000000000..d78abe3a45
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-2.js
@@ -0,0 +1,15 @@
+function foo() {
+ return bar(arguments);
+}
+function bar(argsFromFoo) {
+ var args = Array.prototype.slice.call(argsFromFoo, 1);
+ return baz(args[0], args[1]);
+}
+function baz(a,b) { return a + b; }
+
+var sum = 0;
+with ({}) {}
+for (var i = 0; i < 100; i++) {
+ sum += foo(0, 1, 2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-3.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-3.js
new file mode 100644
index 0000000000..ffe6076177
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-3.js
@@ -0,0 +1,15 @@
+function foo() {
+ return bar(arguments);
+}
+function bar(argsFromFoo) {
+ var args = Array.prototype.slice.call(argsFromFoo, -2);
+ return baz(args[0], args[1]);
+}
+function baz(a,b) { return a + b; }
+
+var sum = 0;
+with ({}) {}
+for (var i = 0; i < 100; i++) {
+ sum += foo(0, 1, 2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-4.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-4.js
new file mode 100644
index 0000000000..f292fe12b7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-4.js
@@ -0,0 +1,15 @@
+function foo() {
+ return bar(arguments);
+}
+function bar(argsFromFoo) {
+ var args = Array.prototype.slice.call(argsFromFoo, 1, 3);
+ return baz(args[0], args[1]);
+}
+function baz(a,b) { return a + b; }
+
+var sum = 0;
+with ({}) {}
+for (var i = 0; i < 100; i++) {
+ sum += foo(0, 1, 2, 3);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-spread.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-spread.js
new file mode 100644
index 0000000000..d4be0829bd
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-spread.js
@@ -0,0 +1,14 @@
+function foo() {
+ return bar(arguments);
+}
+function bar(argsFromFoo) {
+ return baz(...argsFromFoo)
+}
+function baz(a,b) { return a + b; }
+
+var sum = 0;
+with ({}) {}
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-length.js b/js/src/jit-test/tests/arguments/external-arguments-length.js
new file mode 100644
index 0000000000..cac00cccb2
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-length.js
@@ -0,0 +1,14 @@
+function foo(x,y) {
+ with ({}) {}
+ return bar(arguments);
+}
+
+function bar(x) {
+ return x.length + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-mutate-callee.js b/js/src/jit-test/tests/arguments/external-arguments-mutate-callee.js
new file mode 100644
index 0000000000..9cb4af6f1c
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-mutate-callee.js
@@ -0,0 +1,13 @@
+function foo() {
+ arguments.callee = {name: "mutated"};
+ return bar(arguments);
+}
+
+function bar(x) {
+ assertEq(x.callee.name, "mutated");
+ assertEq(arguments.callee.name, "bar");
+}
+
+for (var i = 0; i < 100; i++) {
+ foo();
+}
diff --git a/js/src/jit-test/tests/arguments/external-arguments-set-length.js b/js/src/jit-test/tests/arguments/external-arguments-set-length.js
new file mode 100644
index 0000000000..85ac8a5481
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-set-length.js
@@ -0,0 +1,14 @@
+function foo(x,y) {
+ arguments.length = 3;
+ return bar(arguments);
+}
+
+function bar(x) {
+ return x.length + arguments.length;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 400);
diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-1.js b/js/src/jit-test/tests/arguments/external-arguments-slice-1.js
new file mode 100644
index 0000000000..eeb8dfaccf
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-slice-1.js
@@ -0,0 +1,18 @@
+function foo(x, y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ var args = Array.prototype.slice.call(x);
+ return baz(args[0], args[1]) + arguments.length;
+}
+
+function baz(x, y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1, 2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-2.js b/js/src/jit-test/tests/arguments/external-arguments-slice-2.js
new file mode 100644
index 0000000000..51aa928e39
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-slice-2.js
@@ -0,0 +1,18 @@
+function foo(x, y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ var args = Array.prototype.slice.call(x, 1);
+ return baz(args[0], args[1]) + arguments.length;
+}
+
+function baz(x, y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(0, 1, 2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-3.js b/js/src/jit-test/tests/arguments/external-arguments-slice-3.js
new file mode 100644
index 0000000000..9b58be0465
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-slice-3.js
@@ -0,0 +1,18 @@
+function foo(x, y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ var args = Array.prototype.slice.call(x, -2);
+ return baz(args[0], args[1]) + arguments.length;
+}
+
+function baz(x, y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(0, 1, 2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-4.js b/js/src/jit-test/tests/arguments/external-arguments-slice-4.js
new file mode 100644
index 0000000000..5844fa72e0
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-slice-4.js
@@ -0,0 +1,18 @@
+function foo(x, y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ var args = Array.prototype.slice.call(x, 1, 3);
+ return baz(args[0], args[1]) + arguments.length;
+}
+
+function baz(x, y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(0, 1, 2, 3);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-1.js b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-1.js
new file mode 100644
index 0000000000..fb6fb75a97
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-1.js
@@ -0,0 +1,19 @@
+function foo(x,y) {
+ function capture() { return x; }
+ return bar(arguments);
+}
+
+function bar(x) {
+ var args = Array.prototype.slice.call(x);
+ return baz(args[0], args[1]) + arguments.length;
+}
+
+function baz(x,y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1, 2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-2.js b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-2.js
new file mode 100644
index 0000000000..20a079be98
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-2.js
@@ -0,0 +1,19 @@
+function foo(x,y) {
+ function capture() { return x; }
+ return bar(arguments);
+}
+
+function bar(x) {
+ var args = Array.prototype.slice.call(x, 1);
+ return baz(args[0], args[1]) + arguments.length;
+}
+
+function baz(x,y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(0, 1, 2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-3.js b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-3.js
new file mode 100644
index 0000000000..386594b3bd
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-3.js
@@ -0,0 +1,19 @@
+function foo(x,y) {
+ function capture() { return x; }
+ return bar(arguments);
+}
+
+function bar(x) {
+ var args = Array.prototype.slice.call(x, -2);
+ return baz(args[0], args[1]) + arguments.length;
+}
+
+function baz(x,y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(0, 1, 2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-4.js b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-4.js
new file mode 100644
index 0000000000..f909d79f74
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-4.js
@@ -0,0 +1,19 @@
+function foo(x,y) {
+ function capture() { return x; }
+ return bar(arguments);
+}
+
+function bar(x) {
+ var args = Array.prototype.slice.call(x, 1, 3);
+ return baz(args[0], args[1]) + arguments.length;
+}
+
+function baz(x,y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(0, 1, 2, 3);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-spread-forwarded.js b/js/src/jit-test/tests/arguments/external-arguments-spread-forwarded.js
new file mode 100644
index 0000000000..7a70189c28
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-spread-forwarded.js
@@ -0,0 +1,18 @@
+function foo(x,y) {
+ function capture() { return x; }
+ return bar(arguments);
+}
+
+function bar(x) {
+ return baz(...x) + arguments.length;
+}
+
+function baz(x,y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/external-arguments-spread.js b/js/src/jit-test/tests/arguments/external-arguments-spread.js
new file mode 100644
index 0000000000..cc0f1e18f1
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/external-arguments-spread.js
@@ -0,0 +1,17 @@
+function foo(x,y) {
+ return bar(arguments);
+}
+
+function bar(x) {
+ return baz(...x) + arguments.length;
+}
+
+function baz(x,y) {
+ return x + y;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 400)
diff --git a/js/src/jit-test/tests/arguments/function_dot_caller_restrictions.js b/js/src/jit-test/tests/arguments/function_dot_caller_restrictions.js
new file mode 100644
index 0000000000..414f348eb6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/function_dot_caller_restrictions.js
@@ -0,0 +1,78 @@
+
+function g() { }
+function strict() {
+ "use strict";
+}
+
+let bound = g.bind();
+let arrow = x => 0;
+
+async function fn_async() { }
+function * fn_generator() { }
+
+let o = {
+ mtd() {},
+ get x() {},
+ set x(v) {},
+};
+
+class Base { }
+class Derived extends Base { }
+
+function asm_mod() {
+ "use asm";
+ function mtd() {}
+ return { mtd: mtd }
+}
+
+let asm_fun = (new asm_mod).mtd;
+
+let builtin_selfhost = [].sort;
+let builtin_native = Math.sin;
+
+let dot_caller = Object.getOwnPropertyDescriptor(Function.__proto__,
+ "caller").get;
+
+// Returns true if fn.caller is allowed
+function check(fn) {
+ try {
+ (function() {
+ fn.caller;
+ })();
+ }
+ catch (e) {
+ assertEq(e instanceof TypeError, true);
+ return false;
+ }
+ return true;
+}
+
+// Normal sloppy functions are allowed, even if they also are intended as
+// asm.js.
+assertEq(check(g), true);
+assertEq(check(asm_mod), true);
+assertEq(check(asm_fun), true);
+
+// Most others are not
+assertEq(check(strict), false);
+assertEq(check(bound), false);
+assertEq(check(arrow), false);
+assertEq(check(fn_async), false);
+assertEq(check(fn_generator), false);
+assertEq(check(o.mtd), false)
+assertEq(check(Object.getOwnPropertyDescriptor(o, "x").get), false)
+assertEq(check(Object.getOwnPropertyDescriptor(o, "x").set), false)
+assertEq(check(Base), false);
+assertEq(check(Derived), false);
+assertEq(check(builtin_selfhost), false);
+assertEq(check(builtin_native), false);
+assertEq(check(dot_caller), false);
+
+// Have a native invoke .caller on our behalf.
+function foo() {
+ function inner() {
+ return callFunctionFromNativeFrame(dot_caller.bind(inner))
+ }
+ return inner();
+}
+assertEq(foo, foo());
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-apply-rectifier.js b/js/src/jit-test/tests/arguments/inline-arguments-apply-rectifier.js
new file mode 100644
index 0000000000..299b3cafec
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-apply-rectifier.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function foo(a,b) {
+ with ({}) {}
+ return a + b;
+}
+
+var obj = {};
+function inner(x,y) {
+ assertEq(x + y, foo.apply(obj, arguments));
+}
+
+function outer0() {
+ trialInline();
+ inner();
+}
+
+function outer1() {
+ trialInline();
+ inner(1);
+}
+
+function outer2() {
+ trialInline();
+ inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ inner(1,2,3);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ outer0();
+ outer1();
+ outer2();
+ outer3();
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-apply.js b/js/src/jit-test/tests/arguments/inline-arguments-apply.js
new file mode 100644
index 0000000000..0d46785715
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-apply.js
@@ -0,0 +1,46 @@
+// |jit-test| --fast-warmup
+
+
+function foo(...args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return foo.apply({}, arguments);
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1,2,3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1,2,3,4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 3);
+ assertEq(outer4(), 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-callee.js b/js/src/jit-test/tests/arguments/inline-arguments-callee.js
new file mode 100644
index 0000000000..f825839a0f
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-callee.js
@@ -0,0 +1,16 @@
+function inner() {
+ return arguments.callee;
+}
+function inner_escaped() {
+ return arguments;
+}
+function outer() {
+ assertEq(inner(), inner);
+ assertEq(inner_escaped().callee, inner_escaped);
+ assertEq(arguments.callee, outer);
+}
+
+with({}) {}
+for (var i = 0; i < 100; i++) {
+ outer();
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-apply.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-apply.js
new file mode 100644
index 0000000000..29230abb87
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-apply.js
@@ -0,0 +1,45 @@
+// |jit-test| --fast-warmup
+
+function foo(...args) {
+ with ({}) {}
+ return args.length
+}
+
+function inner() {
+ return arguments;
+}
+
+function outer0() {
+ trialInline();
+ return foo.apply({}, inner());
+}
+
+function outer1() {
+ trialInline();
+ return foo.apply({}, inner(1));
+}
+
+function outer2() {
+ trialInline();
+ return foo.apply({}, inner(1,2));
+}
+
+function outer3() {
+ trialInline();
+ return foo.apply({}, inner(1,2,3));
+}
+
+function outer4() {
+ trialInline();
+ return foo.apply({}, inner(1,2,3,4));
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 3);
+ assertEq(outer4(), 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-exists.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-exists.js
new file mode 100644
index 0000000000..d80959d4b6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-exists.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function inner() {
+ return arguments
+}
+
+function outer0() {
+ trialInline();
+ return 1 in inner();
+}
+
+function outer1() {
+ trialInline();
+ return 1 in inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return 1 in inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return 1 in inner(1,2,3);
+}
+
+function outer4() {
+ trialInline();
+ return 1 in inner(1,2,3,4);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), false);
+ assertEq(outer1(), false);
+ assertEq(outer2(), true);
+ assertEq(outer3(), true);
+ assertEq(outer4(), true);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-oob.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-oob.js
new file mode 100644
index 0000000000..052c564197
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-oob.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function inner() {
+ return arguments
+}
+
+function outer0() {
+ trialInline();
+ return inner()[100];
+}
+
+function outer1() {
+ trialInline();
+ return inner(1)[100];
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2)[100];
+}
+
+function outer3() {
+ trialInline();
+ return inner(1,2,3)[100]
+}
+
+function outer4() {
+ trialInline();
+ return inner(1,2,3,4)[100]
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), undefined);
+ assertEq(outer1(), undefined);
+ assertEq(outer2(), undefined);
+ assertEq(outer3(), undefined);
+ assertEq(outer4(), undefined);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant.js
new file mode 100644
index 0000000000..1a5ffd3cfa
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function inner() {
+ return arguments
+}
+
+function outer0() {
+ trialInline();
+ return inner()[0];
+}
+
+function outer1() {
+ trialInline();
+ return inner(1)[0];
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2)[0];
+}
+
+function outer3() {
+ trialInline();
+ return inner(1,2,3)[0]
+}
+
+function outer4() {
+ trialInline();
+ return inner(1,2,3,4)[0]
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), undefined);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 1);
+ assertEq(outer3(), 1);
+ assertEq(outer4(), 1);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-var.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-var.js
new file mode 100644
index 0000000000..4f3856dfe0
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-var.js
@@ -0,0 +1,44 @@
+// |jit-test| --fast-warmup
+
+var idx;
+
+function inner() {
+ return arguments;
+}
+
+function outer0() {
+ trialInline();
+ return inner()[idx];
+}
+
+function outer1() {
+ trialInline();
+ return inner(0)[idx];
+}
+
+function outer2() {
+ trialInline();
+ return inner(0, 1)[idx];
+}
+
+function outer3() {
+ trialInline();
+ return inner(0,1,2)[idx]
+}
+
+function outer4() {
+ trialInline();
+ return inner(0,1,2,3)[idx]
+}
+
+with ({}) {}
+
+for (idx = 0; idx < 4; idx++) {
+ for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), idx < 0 ? idx : undefined);
+ assertEq(outer1(), idx < 1 ? idx : undefined);
+ assertEq(outer2(), idx < 2 ? idx : undefined);
+ assertEq(outer3(), idx < 3 ? idx : undefined);
+ assertEq(outer4(), idx < 4 ? idx : undefined);
+ }
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-length.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-length.js
new file mode 100644
index 0000000000..2c275dd3d6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-length.js
@@ -0,0 +1,42 @@
+// |jit-test| --fast-warmup
+
+var arg = 0;
+
+function inner() {
+ return arguments;
+}
+
+function outer0() {
+ trialInline();
+ return inner().length;
+}
+
+function outer1() {
+ trialInline();
+ return inner(arg).length;
+}
+
+function outer2() {
+ trialInline();
+ return inner(arg, arg).length;
+}
+
+function outer3() {
+ trialInline();
+ return inner(arg, arg, arg).length;
+}
+
+function outer4() {
+ trialInline();
+ return inner(arg, arg, arg, arg).length;
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 3);
+ assertEq(outer4(), 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-new-spread-optimization.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-new-spread-optimization.js
new file mode 100644
index 0000000000..e576339069
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-new-spread-optimization.js
@@ -0,0 +1,50 @@
+// |jit-test| --fast-warmup
+
+function foo(...args) {
+ with ({}) {}
+ return {result: args.length};
+}
+
+function inner() {
+ return arguments;
+}
+
+function outer0() {
+ trialInline();
+ var args = inner();
+ return new foo(...args);
+}
+
+function outer1() {
+ trialInline();
+ var args = inner(1);
+ return new foo(...args);
+}
+
+function outer2() {
+ trialInline();
+ var args = inner(1,2);
+ return new foo(...args);
+}
+
+function outer3() {
+ trialInline();
+ var args = inner(1,2,3);
+ return new foo(...args);
+}
+
+function outer4() {
+ trialInline();
+ var args = inner(1,2,3,4);
+ return new foo(...args);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0().result, 0);
+ assertEq(outer1().result, 1);
+ assertEq(outer2().result, 2);
+ assertEq(outer3().result, 3);
+ assertEq(outer4().result, 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-1.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-1.js
new file mode 100644
index 0000000000..e428f87e89
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-1.js
@@ -0,0 +1,50 @@
+// |jit-test| --fast-warmup
+
+function foo(args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return arguments;
+}
+
+function outer0() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner());
+ return foo(args);
+}
+
+function outer1() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1));
+ return foo(args);
+}
+
+function outer2() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2));
+ return foo(args);
+}
+
+function outer3() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2, 3));
+ return foo(args);
+}
+
+function outer4() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2, 3, 4));
+ return foo(args);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 3);
+ assertEq(outer4(), 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-2.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-2.js
new file mode 100644
index 0000000000..4c831b99f6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-2.js
@@ -0,0 +1,50 @@
+// |jit-test| --fast-warmup
+
+function foo(args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return arguments;
+}
+
+function outer0() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(), 1);
+ return foo(args);
+}
+
+function outer1() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1), 1);
+ return foo(args);
+}
+
+function outer2() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2), 1);
+ return foo(args);
+}
+
+function outer3() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2, 3), 1);
+ return foo(args);
+}
+
+function outer4() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2, 3, 4), 1);
+ return foo(args);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 0);
+ assertEq(outer2(), 1);
+ assertEq(outer3(), 2);
+ assertEq(outer4(), 3);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-3.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-3.js
new file mode 100644
index 0000000000..1e354140af
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-3.js
@@ -0,0 +1,50 @@
+// |jit-test| --fast-warmup
+
+function foo(args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return arguments;
+}
+
+function outer0() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(), -2);
+ return foo(args);
+}
+
+function outer1() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1), -2);
+ return foo(args);
+}
+
+function outer2() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2), -2);
+ return foo(args);
+}
+
+function outer3() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2, 3), -2);
+ return foo(args);
+}
+
+function outer4() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2, 3, 4), -2);
+ return foo(args);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 2);
+ assertEq(outer4(), 2);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-4.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-4.js
new file mode 100644
index 0000000000..f12410b08f
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-4.js
@@ -0,0 +1,50 @@
+// |jit-test| --fast-warmup
+
+function foo(args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return arguments;
+}
+
+function outer0() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(), 1, 3);
+ return foo(args);
+}
+
+function outer1() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1), 1, 3);
+ return foo(args);
+}
+
+function outer2() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2), 1, 3);
+ return foo(args);
+}
+
+function outer3() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2, 3), 1, 3);
+ return foo(args);
+}
+
+function outer4() {
+ trialInline();
+ var args = Array.prototype.slice.call(inner(1, 2, 3, 4), 1, 3);
+ return foo(args);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 0);
+ assertEq(outer2(), 1);
+ assertEq(outer3(), 2);
+ assertEq(outer4(), 2);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-spread-optimization.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-spread-optimization.js
new file mode 100644
index 0000000000..a5092339e3
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-spread-optimization.js
@@ -0,0 +1,50 @@
+// |jit-test| --fast-warmup
+
+function foo(...args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return arguments;
+}
+
+function outer0() {
+ trialInline();
+ var args = inner();
+ return foo(...args);
+}
+
+function outer1() {
+ trialInline();
+ var args = inner(1);
+ return foo(...args);
+}
+
+function outer2() {
+ trialInline();
+ var args = inner(1,2);
+ return foo(...args);
+}
+
+function outer3() {
+ trialInline();
+ var args = inner(1,2,3);
+ return foo(...args);
+}
+
+function outer4() {
+ trialInline();
+ var args = inner(1,2,3,4);
+ return foo(...args);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 3);
+ assertEq(outer4(), 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-1.js b/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-1.js
new file mode 100644
index 0000000000..21dbbb0863
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-1.js
@@ -0,0 +1,34 @@
+// |jit-test| --fast-warmup
+
+function inner(i) {
+ return i in arguments;
+}
+
+function outer(i) {
+ trialInline();
+
+ // Loop header to trigger OSR.
+ let r = 0;
+ for (let j = 0; j < 1; ++j) {
+ r += inner(i,
+ // Add extra arguments to ensure we read the arguments from the frame.
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ );
+ }
+ return r;
+}
+
+let count = 0;
+
+for (let i = 0; i <= 100; ++i) {
+ if (i === 50) {
+ Object.prototype[-1] = 0;
+ }
+ count += outer(i < 100 ? i : -1);
+}
+
+assertEq(count, 1 + 21);
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-2.js b/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-2.js
new file mode 100644
index 0000000000..52e877d549
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-2.js
@@ -0,0 +1,27 @@
+// |jit-test| --fast-warmup
+
+function inner(i) {
+ return i in arguments;
+}
+
+function outer(i) {
+ trialInline();
+
+ // Loop header to trigger OSR.
+ let r = 0;
+ for (let j = 0; j < 1; ++j) {
+ r += inner(i);
+ }
+ return r;
+}
+
+let count = 0;
+
+for (let i = 0; i <= 100; ++i) {
+ if (i === 50) {
+ Object.prototype[-1] = 0;
+ }
+ count += outer(i < 100 ? i : -1);
+}
+
+assertEq(count, 1 + 1);
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-formals.js b/js/src/jit-test/tests/arguments/inline-arguments-formals.js
new file mode 100644
index 0000000000..8b081999b6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-formals.js
@@ -0,0 +1,37 @@
+// |jit-test| --fast-warmup
+
+var dummy;
+
+function inner(x,y) {
+ dummy = arguments.length;
+ return y;
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(0);
+}
+
+function outer2() {
+ trialInline();
+ return inner(0, 1);
+}
+
+function outer3() {
+ trialInline();
+ return inner(0,1,2);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), undefined);
+ assertEq(outer1(), undefined);
+ assertEq(outer2(), 1);
+ assertEq(outer3(), 1);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-index-constant-exists.js b/js/src/jit-test/tests/arguments/inline-arguments-index-constant-exists.js
new file mode 100644
index 0000000000..f6f90c63a2
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-index-constant-exists.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function inner() {
+ return 1 in arguments;
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1,2,3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1,2,3,4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), false);
+ assertEq(outer1(), false);
+ assertEq(outer2(), true);
+ assertEq(outer3(), true);
+ assertEq(outer4(), true);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-index-constant-oob.js b/js/src/jit-test/tests/arguments/inline-arguments-index-constant-oob.js
new file mode 100644
index 0000000000..4e1dc925e1
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-index-constant-oob.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function inner() {
+ return arguments[100]
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1,2,3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1,2,3,4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), undefined);
+ assertEq(outer1(), undefined);
+ assertEq(outer2(), undefined);
+ assertEq(outer3(), undefined);
+ assertEq(outer4(), undefined);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-index-constant.js b/js/src/jit-test/tests/arguments/inline-arguments-index-constant.js
new file mode 100644
index 0000000000..41ef531d22
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-index-constant.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function inner() {
+ return arguments[0]
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1,2,3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1,2,3,4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), undefined);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 1);
+ assertEq(outer3(), 1);
+ assertEq(outer4(), 1);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-index-var.js b/js/src/jit-test/tests/arguments/inline-arguments-index-var.js
new file mode 100644
index 0000000000..21a71d2c29
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-index-var.js
@@ -0,0 +1,44 @@
+// |jit-test| --fast-warmup
+
+var idx;
+
+function inner() {
+ return arguments[idx]
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(0);
+}
+
+function outer2() {
+ trialInline();
+ return inner(0, 1);
+}
+
+function outer3() {
+ trialInline();
+ return inner(0,1,2)
+}
+
+function outer4() {
+ trialInline();
+ return inner(0,1,2,3)
+}
+
+with ({}) {}
+
+for (idx = 0; idx < 4; idx++) {
+ for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), idx < 0 ? idx : undefined);
+ assertEq(outer1(), idx < 1 ? idx : undefined);
+ assertEq(outer2(), idx < 2 ? idx : undefined);
+ assertEq(outer3(), idx < 3 ? idx : undefined);
+ assertEq(outer4(), idx < 4 ? idx : undefined);
+ }
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-length.js b/js/src/jit-test/tests/arguments/inline-arguments-length.js
new file mode 100644
index 0000000000..efd9dedaf7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-length.js
@@ -0,0 +1,42 @@
+// |jit-test| --fast-warmup
+
+var arg = 0;
+
+function inner() {
+ return arguments.length;
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(arg);
+}
+
+function outer2() {
+ trialInline();
+ return inner(arg, arg);
+}
+
+function outer3() {
+ trialInline();
+ return inner(arg, arg, arg);
+}
+
+function outer4() {
+ trialInline();
+ return inner(arg, arg, arg, arg);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 3);
+ assertEq(outer4(), 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization-rectifier.js b/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization-rectifier.js
new file mode 100644
index 0000000000..6aa15d876f
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization-rectifier.js
@@ -0,0 +1,39 @@
+// |jit-test| --fast-warmup
+
+function foo(a,b) {
+ with ({}) {}
+ return {result: a + b};
+}
+
+function inner(x,y) {
+ assertEq(x + y, new foo(...arguments).result);
+}
+
+function outer0() {
+ trialInline();
+ inner();
+}
+
+function outer1() {
+ trialInline();
+ inner(1);
+}
+
+function outer2() {
+ trialInline();
+ inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ inner(1,2,3);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ outer0();
+ outer1();
+ outer2();
+ outer3();
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization.js b/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization.js
new file mode 100644
index 0000000000..2dab581e68
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization.js
@@ -0,0 +1,47 @@
+// |jit-test| --fast-warmup
+
+
+function foo(...args) {
+ with ({}) {}
+ return {result: args.length};
+}
+
+function inner() {
+ // Single argument spread calls with |arguments| can be optimised.
+ return new foo(...arguments);
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1,2,3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1,2,3,4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0().result, 0);
+ assertEq(outer1().result, 1);
+ assertEq(outer2().result, 2);
+ assertEq(outer3().result, 3);
+ assertEq(outer4().result, 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-1.js b/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-1.js
new file mode 100644
index 0000000000..b60140b3a6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-1.js
@@ -0,0 +1,39 @@
+// |jit-test| --fast-warmup
+
+function inner(i) {
+ // Can't be eliminated because negative indices cause a bailout.
+ arguments[i];
+ arguments[i];
+ arguments[i];
+}
+
+function outer(i) {
+ trialInline();
+
+ // Loop header to trigger OSR.
+ for (let j = 0; j < 1; ++j) {
+ inner(i,
+ // Add extra arguments to ensure we read the arguments from the frame.
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ );
+ }
+}
+
+let count = 0;
+
+for (let i = 0; i <= 100; ++i) {
+ if (i === 50) {
+ Object.defineProperty(Object.prototype, -1, {
+ get() {
+ count++;
+ }
+ });
+ }
+ outer(i < 100 ? i : -1);
+}
+
+assertEq(count, 3);
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-2.js b/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-2.js
new file mode 100644
index 0000000000..e5c9f0cd6e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-2.js
@@ -0,0 +1,32 @@
+// |jit-test| --fast-warmup
+
+function inner(i) {
+ // Can't be eliminated because negative indices cause a bailout.
+ arguments[i];
+ arguments[i];
+ arguments[i];
+}
+
+function outer(i) {
+ trialInline();
+
+ // Loop header to trigger OSR.
+ for (let j = 0; j < 1; ++j) {
+ inner(i);
+ }
+}
+
+let count = 0;
+
+for (let i = 0; i <= 100; ++i) {
+ if (i === 50) {
+ Object.defineProperty(Object.prototype, -1, {
+ get() {
+ count++;
+ }
+ });
+ }
+ outer(i < 100 ? i : -1);
+}
+
+assertEq(count, 3);
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-profiler.js b/js/src/jit-test/tests/arguments/inline-arguments-profiler.js
new file mode 100644
index 0000000000..6d89b3d72b
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-profiler.js
@@ -0,0 +1,11 @@
+function foo() { return arguments; }
+function bar(x) { return foo(x); }
+
+// Turning on the profiler uses up a register and increases register pressure.
+enableGeckoProfiling();
+with ({}) {}
+for (var i = 0; i < 100; i++) {
+ var result = bar(3);
+ assertEq(result.length, 1);
+ assertEq(result[0], 3);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-1.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-1.js
new file mode 100644
index 0000000000..19021aae4a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-1.js
@@ -0,0 +1,46 @@
+// |jit-test| --fast-warmup
+
+
+function foo(args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return foo(Array.prototype.slice.call(arguments));
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1, 2, 3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1, 2, 3, 4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 3);
+ assertEq(outer4(), 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-2.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-2.js
new file mode 100644
index 0000000000..f3af77f844
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-2.js
@@ -0,0 +1,46 @@
+// |jit-test| --fast-warmup
+
+
+function foo(args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return foo(Array.prototype.slice.call(arguments, 1));
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1, 2, 3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1, 2, 3, 4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 0);
+ assertEq(outer2(), 1);
+ assertEq(outer3(), 2);
+ assertEq(outer4(), 3);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-3.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-3.js
new file mode 100644
index 0000000000..af16586d6c
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-3.js
@@ -0,0 +1,46 @@
+// |jit-test| --fast-warmup
+
+
+function foo(args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return foo(Array.prototype.slice.call(arguments, -2));
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1, 2, 3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1, 2, 3, 4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 2);
+ assertEq(outer4(), 2);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-4.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-4.js
new file mode 100644
index 0000000000..26cf0563af
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-4.js
@@ -0,0 +1,46 @@
+// |jit-test| --fast-warmup
+
+
+function foo(args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ return foo(Array.prototype.slice.call(arguments, 1, 3));
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1, 2, 3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1, 2, 3, 4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 0);
+ assertEq(outer2(), 1);
+ assertEq(outer3(), 2);
+ assertEq(outer4(), 2);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-5.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-5.js
new file mode 100644
index 0000000000..725b14b752
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-5.js
@@ -0,0 +1,97 @@
+// |jit-test| --fast-warmup
+
+function blackhole() {
+ // Prevent Ion from optimising away this function and its arguments.
+ with ({});
+}
+
+function inner() {
+ // Compile-time constants after GVN, but not during scalar replacement.
+ // We don't want these to be constants during scalar replacement to ensure
+ // we don't optimise away the slice() call.
+ const zero = Math.pow(0, 1);
+ const one = Math.pow(1, 1);
+ const two = Math.pow(2, 1);
+ const three = Math.pow(3, 1);
+ const four = Math.pow(4, 1);
+
+ // Test with constant |begin| and |count| a constant after GVN.
+ {
+ let a0 = Array.prototype.slice.call(arguments, 0, zero);
+ let a1 = Array.prototype.slice.call(arguments, 0, one);
+ let a2 = Array.prototype.slice.call(arguments, 0, two);
+ let a3 = Array.prototype.slice.call(arguments, 0, three);
+ let a4 = Array.prototype.slice.call(arguments, 0, four);
+ blackhole(a0, a1, a2, a3, a4);
+ }
+ {
+ let a0 = Array.prototype.slice.call(arguments, 1, zero);
+ let a1 = Array.prototype.slice.call(arguments, 1, one);
+ let a2 = Array.prototype.slice.call(arguments, 1, two);
+ let a3 = Array.prototype.slice.call(arguments, 1, three);
+ let a4 = Array.prototype.slice.call(arguments, 1, four);
+ blackhole(a0, a1, a2, a3, a4);
+ }
+
+ // Same as above, but this time |begin| isn't a constant during scalar replacement.
+ {
+ let a0 = Array.prototype.slice.call(arguments, zero, zero);
+ let a1 = Array.prototype.slice.call(arguments, zero, one);
+ let a2 = Array.prototype.slice.call(arguments, zero, two);
+ let a3 = Array.prototype.slice.call(arguments, zero, three);
+ let a4 = Array.prototype.slice.call(arguments, zero, four);
+ blackhole(a0, a1, a2, a3, a4);
+ }
+ {
+ let a0 = Array.prototype.slice.call(arguments, one, zero);
+ let a1 = Array.prototype.slice.call(arguments, one, one);
+ let a2 = Array.prototype.slice.call(arguments, one, two);
+ let a3 = Array.prototype.slice.call(arguments, one, three);
+ let a4 = Array.prototype.slice.call(arguments, one, four);
+ blackhole(a0, a1, a2, a3, a4);
+ }
+}
+
+// Ensure |inner| can be inlined.
+assertEq(isSmallFunction(inner), true);
+
+// Zero arguments.
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+// One argument.
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+// Two arguments.
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+// Three arguments.
+function outer3() {
+ trialInline();
+ return inner(1, 2, 3);
+}
+
+// Four arguments. (|inner| can't be inlined anymore!)
+function outer4() {
+ trialInline();
+ return inner(1, 2, 3, 4);
+}
+
+// Don't Ion compile the top-level script.
+with ({});
+
+for (var i = 0; i < 50; i++) {
+ outer0();
+ outer1();
+ outer2();
+ outer3();
+ outer4();
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-1.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-1.js
new file mode 100644
index 0000000000..f17d6b20a9
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-1.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function foo(a, b) {
+ with ({}) {}
+ return a + b;
+}
+
+function inner(x, y) {
+ var args = Array.prototype.slice.call(arguments);
+ assertEq(x + y, foo(args[0], args[1]));
+}
+
+function outer0() {
+ trialInline();
+ inner();
+}
+
+function outer1() {
+ trialInline();
+ inner(1);
+}
+
+function outer2() {
+ trialInline();
+ inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ inner(1, 2, 3);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ outer0();
+ outer1();
+ outer2();
+ outer3();
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-2.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-2.js
new file mode 100644
index 0000000000..ad6f8cfcd5
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-2.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function foo(a, b) {
+ with ({}) {}
+ return a + b;
+}
+
+function inner(x, y, z) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ assertEq(y + z, foo(args[0], args[1]));
+}
+
+function outer0() {
+ trialInline();
+ inner();
+}
+
+function outer1() {
+ trialInline();
+ inner(1);
+}
+
+function outer2() {
+ trialInline();
+ inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ inner(1, 2, 3);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ outer0();
+ outer1();
+ outer2();
+ outer3();
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-3.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-3.js
new file mode 100644
index 0000000000..083c4ace68
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-3.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function foo(a, b) {
+ with ({}) {}
+ return a + b;
+}
+
+function inner(x, y, z) {
+ var args = Array.prototype.slice.call(arguments, -2);
+ assertEq((z !== undefined ? y + z : x + y), foo(args[0], args[1]));
+}
+
+function outer0() {
+ trialInline();
+ inner();
+}
+
+function outer1() {
+ trialInline();
+ inner(1);
+}
+
+function outer2() {
+ trialInline();
+ inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ inner(1, 2, 3);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ outer0();
+ outer1();
+ outer2();
+ outer3();
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-4.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-4.js
new file mode 100644
index 0000000000..a7a63d77a8
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-4.js
@@ -0,0 +1,40 @@
+// |jit-test| --fast-warmup
+
+function foo(a, b) {
+ with ({}) {}
+ return a + b;
+}
+
+function inner(w, x, y, z) {
+ var args = Array.prototype.slice.call(arguments, 1, 3);
+ assertEq(x + y, foo(args[0], args[1]));
+}
+
+function outer0() {
+ trialInline();
+ inner();
+}
+
+function outer1() {
+ trialInline();
+ inner(1);
+}
+
+function outer2() {
+ trialInline();
+ inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ inner(1, 2, 3);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ outer0();
+ outer1();
+ outer2();
+ outer3();
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization-rectifier.js b/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization-rectifier.js
new file mode 100644
index 0000000000..a89abcdc0b
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization-rectifier.js
@@ -0,0 +1,39 @@
+// |jit-test| --fast-warmup
+
+function foo(a,b) {
+ with ({}) {}
+ return a + b;
+}
+
+function inner(x,y) {
+ assertEq(x + y, foo(...arguments));
+}
+
+function outer0() {
+ trialInline();
+ inner();
+}
+
+function outer1() {
+ trialInline();
+ inner(1);
+}
+
+function outer2() {
+ trialInline();
+ inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ inner(1,2,3);
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ outer0();
+ outer1();
+ outer2();
+ outer3();
+}
diff --git a/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization.js b/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization.js
new file mode 100644
index 0000000000..21505e9437
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization.js
@@ -0,0 +1,47 @@
+// |jit-test| --fast-warmup
+
+
+function foo(...args) {
+ with ({}) {}
+ return args.length;
+}
+
+function inner() {
+ // Single argument spread calls with |arguments| can be optimised.
+ return foo(...arguments);
+}
+
+function outer0() {
+ trialInline();
+ return inner();
+}
+
+function outer1() {
+ trialInline();
+ return inner(1);
+}
+
+function outer2() {
+ trialInline();
+ return inner(1, 2);
+}
+
+function outer3() {
+ trialInline();
+ return inner(1,2,3)
+}
+
+function outer4() {
+ trialInline();
+ return inner(1,2,3,4)
+}
+
+with ({}) {}
+
+for (var i = 0; i < 50; i++) {
+ assertEq(outer0(), 0);
+ assertEq(outer1(), 1);
+ assertEq(outer2(), 2);
+ assertEq(outer3(), 3);
+ assertEq(outer4(), 4);
+}
diff --git a/js/src/jit-test/tests/arguments/inline-rest-array-creation.js b/js/src/jit-test/tests/arguments/inline-rest-array-creation.js
new file mode 100644
index 0000000000..34998d4cb4
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-rest-array-creation.js
@@ -0,0 +1,83 @@
+function zero(...rest)
+{
+ assertEq(rest.length, 0, "zero rest wrong length");
+}
+
+function tzero()
+{
+ zero();
+}
+
+tzero(); tzero(); tzero();
+
+function one(...rest)
+{
+ assertEq(rest.length, 1, "one rest wrong length");
+}
+
+function tone()
+{
+ one(0);
+}
+
+tone(); tone(); tone();
+
+function two(...rest)
+{
+ assertEq(rest.length, 2, "two rest wrong length");
+}
+
+function ttwo()
+{
+ two(0, 1);
+}
+
+ttwo(); ttwo(); ttwo();
+
+function zeroWithLeading0(x, ...rest)
+{
+ assertEq(rest.length, 0, "zeroWithLeading0 rest wrong length");
+}
+
+function tzeroWithLeading0()
+{
+ zeroWithLeading0();
+}
+
+tzeroWithLeading0(); tzeroWithLeading0(); tzeroWithLeading0();
+
+function zeroWithLeading1(x, ...rest)
+{
+ assertEq(rest.length, 0, "zeroWithLeading1 rest wrong length");
+}
+
+function tzeroWithLeading1()
+{
+ zeroWithLeading1(0);
+}
+
+tzeroWithLeading1(); tzeroWithLeading1(); tzeroWithLeading1();
+
+function oneWithLeading(x, ...rest)
+{
+ assertEq(rest.length, 1, "oneWithLeading rest wrong length");
+}
+
+function toneWithLeading()
+{
+ oneWithLeading(0, 1);
+}
+
+toneWithLeading(); toneWithLeading(); toneWithLeading();
+
+function twoWithLeading(x, ...rest)
+{
+ assertEq(rest.length, 2, "twoWithLeading rest wrong length");
+}
+
+function ttwoWithLeading()
+{
+ twoWithLeading(0, 1, 2);
+}
+
+ttwoWithLeading(); ttwoWithLeading(); ttwoWithLeading();
diff --git a/js/src/jit-test/tests/arguments/inline-transpile.js b/js/src/jit-test/tests/arguments/inline-transpile.js
new file mode 100644
index 0000000000..0720256593
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/inline-transpile.js
@@ -0,0 +1,17 @@
+function foo(i) {
+ return i;
+}
+
+function bar(n) {
+ return foo.apply({}, arguments);
+}
+
+function baz(a, n) {
+ return bar(n);
+}
+
+var sum = 0;
+for (var i = 0; i < 10000; i++) {
+ sum += baz(0, 1);
+}
+assertEq(sum, 10000);
diff --git a/js/src/jit-test/tests/arguments/iterator-set-and-redefine.js b/js/src/jit-test/tests/arguments/iterator-set-and-redefine.js
new file mode 100644
index 0000000000..bcf182790f
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/iterator-set-and-redefine.js
@@ -0,0 +1,33 @@
+function mapped() {
+ var Iterator = {};
+
+ // First overwrite the iterator.
+ arguments[Symbol.iterator] = Iterator;
+
+ // And then redefine a property attribute.
+ Object.defineProperty(arguments, Symbol.iterator, {
+ writable: false
+ });
+
+ // Make sure redefining an attribute doesn't reset the iterator value.
+ assertEq(arguments[Symbol.iterator], Iterator);
+}
+mapped();
+
+function unmapped() {
+ "use strict";
+
+ var Iterator = {};
+
+ // First overwrite the iterator.
+ arguments[Symbol.iterator] = Iterator;
+
+ // And then redefine a property attribute.
+ Object.defineProperty(arguments, Symbol.iterator, {
+ writable: false
+ });
+
+ // Make sure redefining an attribute doesn't reset the iterator value.
+ assertEq(arguments[Symbol.iterator], Iterator);
+}
+unmapped();
diff --git a/js/src/jit-test/tests/arguments/mapped-define.js b/js/src/jit-test/tests/arguments/mapped-define.js
new file mode 100644
index 0000000000..0c806f618b
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/mapped-define.js
@@ -0,0 +1,81 @@
+load(libdir + "asserts.js");
+
+function testMapped(a) {
+ assertEq(arguments[0], 1);
+
+ Object.defineProperty(arguments, 0, {value: 23, writable: true, configurable: true});
+ assertEq(arguments[0], 23);
+ assertEq(a, 23);
+
+ a = 12;
+ assertEq(a, 12);
+ assertEq(arguments[0], 12);
+
+ Object.defineProperty(arguments, 0, {value: 9, writable: false, configurable: false});
+ assertEq(arguments[0], 9);
+ assertEq(a, 9);
+
+ a = 4;
+ assertEq(arguments[0], 9);
+ assertEq(a, 4);
+}
+for (var i = 0; i < 5; i++) {
+ testMapped(1);
+}
+
+function testAttributes(x) {
+ Object.defineProperty(arguments, 0, {enumerable:true,
+ writable:true,
+ configurable:true,
+ value: 4});
+
+ // Should inherit enumerable/configurable attributes.
+ Object.defineProperty(arguments, 0, {writable:true,
+ value: 8});
+ assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(arguments, 0)),
+ '{"value":8,"writable":true,"enumerable":true,"configurable":true}');
+ assertEq(x, 8);
+
+ // Property becomes non-configurable.
+ Object.defineProperty(arguments, 0, {writable:true,
+ configurable:false,
+ value: 6});
+ assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(arguments, 0)),
+ '{"value":6,"writable":true,"enumerable":true,"configurable":false}');
+ assertEq(x, 6);
+
+ // Can no longer make it non-enumerable.
+ assertThrowsInstanceOf(() => Object.defineProperty(arguments, 0, {writable:true,
+ configurable:false,
+ enumerable:false,
+ value: 6}),
+ TypeError);
+
+ // Can no longer make it configurable.
+ assertThrowsInstanceOf(() => Object.defineProperty(arguments, 0, {writable:true,
+ configurable:true,
+ value: 6}),
+ TypeError);
+
+ // Can still make it non-writable.
+ Object.defineProperty(arguments, 0, {writable:false,
+ enumerable:true,
+ configurable:false,
+ value: 3});
+ assertEq(x, 3);
+
+ // No longer a mapped property.
+ x = 5;
+ assertEq(arguments[0], 3);
+
+ // Can no longer make it writable.
+ assertThrowsInstanceOf(() => Object.defineProperty(arguments, 0, {writable:true,
+ enumerable:true,
+ configurable:false,
+ value: 5}),
+ TypeError);
+ assertEq(x, 5);
+}
+for (var i = 0; i < 5; i++) {
+ testAttributes(i);
+}
diff --git a/js/src/jit-test/tests/arguments/mapped-freeze.js b/js/src/jit-test/tests/arguments/mapped-freeze.js
new file mode 100644
index 0000000000..e60cb24233
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/mapped-freeze.js
@@ -0,0 +1,8 @@
+function f(a) {
+ Object.freeze(arguments);
+ a = 1;
+ return arguments[0];
+}
+
+assertEq(f(10), 10);
+assertEq(f("hello"), "hello");
diff --git a/js/src/jit-test/tests/arguments/mapped-unmapped-args.js b/js/src/jit-test/tests/arguments/mapped-unmapped-args.js
new file mode 100644
index 0000000000..d1b063be3d
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/mapped-unmapped-args.js
@@ -0,0 +1,61 @@
+// An unmapped arguments object is created for strict functions or functions
+// with default/rest/destructuring args.
+
+load(libdir + "asserts.js");
+
+function testDefaults(a, b=3) {
+ a = 3;
+ b = 4;
+ assertEq(arguments.length, 1);
+ assertEq(arguments[0], 1);
+ assertEq(arguments[1], undefined);
+ arguments[0] = 5;
+ assertEq(a, 3);
+ assertThrowsInstanceOf(() => arguments.callee, TypeError);
+}
+testDefaults(1);
+
+function testRest(a, ...rest) {
+ a = 3;
+ assertEq(arguments.length, 3);
+ assertEq(arguments[0], 1);
+ assertEq(arguments[1], 2);
+ arguments[0] = 5;
+ assertEq(a, 3);
+ arguments[1] = 6;
+ assertEq(arguments[1], 6);
+ assertEq(rest.toString(), "2,3");
+ assertThrowsInstanceOf(() => arguments.callee, TypeError);
+}
+testRest(1, 2, 3);
+
+function testDestructuring(a, {foo, bar}, b) {
+ a = 3;
+ bar = 4;
+ b = 1;
+ assertEq(arguments.length, 3);
+ assertEq(arguments[0], 1);
+ assertEq(arguments[1].bar, 2);
+ assertEq(arguments[2], 9);
+ assertThrowsInstanceOf(() => arguments.callee, TypeError);
+}
+testDestructuring(1, {foo: 1, bar: 2}, 9);
+
+function testStrict(a) {
+ "use strict";
+ a = 3;
+ assertEq(arguments[0], 1);
+ arguments[0] = 8;
+ assertEq(a, 3);
+ assertThrowsInstanceOf(() => arguments.callee, TypeError);
+}
+testStrict(1, 2);
+
+function testMapped(a) {
+ a = 3;
+ assertEq(arguments[0], 3);
+ arguments[0] = 5;
+ assertEq(a, 5);
+ assertEq(arguments.callee, testMapped);
+}
+testMapped(1);
diff --git a/js/src/jit-test/tests/arguments/nonstrict-args.js b/js/src/jit-test/tests/arguments/nonstrict-args.js
new file mode 100644
index 0000000000..750bcc1e78
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/nonstrict-args.js
@@ -0,0 +1,24 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function args(a) { return arguments; }
+
+var a1, a2, a3, a4;
+
+for (var i = 0; i < 5; i++)
+{
+ a1 = args();
+ a2 = args(1);
+ a3 = args(1, obj);
+ a4 = args("foopy");
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [1]), true);
+assertEq(arraysEqual(a3, [1, obj]), true);
+assertEq(arraysEqual(a4, ["foopy"]), true);
diff --git a/js/src/jit-test/tests/arguments/nonstrict-assign-element-get-parameter.js b/js/src/jit-test/tests/arguments/nonstrict-assign-element-get-parameter.js
new file mode 100644
index 0000000000..c55588daa4
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/nonstrict-assign-element-get-parameter.js
@@ -0,0 +1,13 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+function assignElementGetParameter(a)
+{
+ arguments[0] = 17;
+ return a;
+}
+
+for (var i = 0; i < 5; i++)
+ assertEq(assignElementGetParameter(42), 17);
diff --git a/js/src/jit-test/tests/arguments/nonstrict-assign-parameter-get-element.js b/js/src/jit-test/tests/arguments/nonstrict-assign-parameter-get-element.js
new file mode 100644
index 0000000000..747abbad31
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/nonstrict-assign-parameter-get-element.js
@@ -0,0 +1,13 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+function assignParameterGetElement(a)
+{
+ a = 17;
+ return arguments[0];
+}
+
+for (var i = 0; i < 5; i++)
+ assertEq(assignParameterGetElement(42), 17);
diff --git a/js/src/jit-test/tests/arguments/nonstrict-assign.js b/js/src/jit-test/tests/arguments/nonstrict-assign.js
new file mode 100644
index 0000000000..8dd75e7209
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/nonstrict-assign.js
@@ -0,0 +1,17 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+function assign(a)
+{
+ a = 17;
+ return arguments;
+}
+
+var a1;
+for (var i = 0; i < 5; i++)
+ a1 = assign(1);
+
+assertEq(arraysEqual(a1, [17]), true);
diff --git a/js/src/jit-test/tests/arguments/nonstrict-later-assign.js b/js/src/jit-test/tests/arguments/nonstrict-later-assign.js
new file mode 100644
index 0000000000..fbf72abc4c
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/nonstrict-later-assign.js
@@ -0,0 +1,18 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+function getLaterAssign(a)
+{
+ var o = arguments;
+ a = 17;
+ return o;
+}
+
+var a1, a2;
+for (var i = 0; i < 5; i++)
+ a1 = getLaterAssign(1);
+
+assertEq(arraysEqual(a1, [17]), true);
diff --git a/js/src/jit-test/tests/arguments/nonstrict-noargs.js b/js/src/jit-test/tests/arguments/nonstrict-noargs.js
new file mode 100644
index 0000000000..ef1bca7dee
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/nonstrict-noargs.js
@@ -0,0 +1,21 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function noargs() { return arguments; }
+
+var a1, a2, a3;
+for (var i = 0; i < 5; i++)
+{
+ a1 = noargs();
+ a2 = noargs(1);
+ a3 = noargs(2, obj, 8);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [1]), true);
+assertEq(arraysEqual(a3, [2, obj, 8]), true);
diff --git a/js/src/jit-test/tests/arguments/polymorphic-getelem.js b/js/src/jit-test/tests/arguments/polymorphic-getelem.js
new file mode 100644
index 0000000000..95672c7ca7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/polymorphic-getelem.js
@@ -0,0 +1,15 @@
+function foo(s) {
+ return arguments[s];
+}
+
+for (var i = 0; i < 100; i++) {
+ assertEq(foo("callee"), foo);
+}
+
+for (var i = 0; i < 100; i++) {
+ assertEq(foo("length"), 1);
+}
+
+for (var i = 0; i < 100; i++) {
+ assertEq(foo(0), 0);
+}
diff --git a/js/src/jit-test/tests/arguments/recover-osr-arguments-oob.js b/js/src/jit-test/tests/arguments/recover-osr-arguments-oob.js
new file mode 100644
index 0000000000..72e322dd85
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/recover-osr-arguments-oob.js
@@ -0,0 +1,27 @@
+setJitCompilerOption("baseline.warmup.trigger", 0);
+setJitCompilerOption("ion.warmup.trigger", 120);
+gczeal(0);
+with ({}) {}
+
+function bar(i) {
+ // |arguments| can be recovered, even if this is inlined into an OSR script.
+ assertRecoveredOnBailout(arguments, true);
+ return arguments[i & 1]|0;
+}
+
+function foo(n) {
+ // |arguments| for an OSR script can't be recovered.
+ assertRecoveredOnBailout(arguments, false);
+ var sum = 0;
+ for (var i = 0; i < n; i++) {
+ sum += bar(i);
+ }
+ trialInline();
+ return sum;
+}
+
+// Trigger trial-inlining of bar into foo.
+foo(110);
+
+// OSR-compile foo.
+assertEq(foo(1000), 249500);
diff --git a/js/src/jit-test/tests/arguments/recover-osr-arguments.js b/js/src/jit-test/tests/arguments/recover-osr-arguments.js
new file mode 100644
index 0000000000..88756d4a54
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/recover-osr-arguments.js
@@ -0,0 +1,27 @@
+setJitCompilerOption("baseline.warmup.trigger", 0);
+setJitCompilerOption("ion.warmup.trigger", 120);
+gczeal(0);
+with ({}) {}
+
+function bar() {
+ // |arguments| can be recovered, even if this is inlined into an OSR script.
+ assertRecoveredOnBailout(arguments, true);
+ return arguments[0];
+}
+
+function foo(n) {
+ // |arguments| for an OSR script can't be recovered.
+ assertRecoveredOnBailout(arguments, false);
+ var sum = 0;
+ for (var i = 0; i < n; i++) {
+ sum += bar(i);
+ }
+ trialInline();
+ return sum;
+}
+
+// Trigger trial-inlining of bar into foo.
+foo(110);
+
+// OSR-compile foo.
+assertEq(foo(1000), 499500);
diff --git a/js/src/jit-test/tests/arguments/recover-spread-opt-arguments-after-bail.js b/js/src/jit-test/tests/arguments/recover-spread-opt-arguments-after-bail.js
new file mode 100644
index 0000000000..c8c76c278a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/recover-spread-opt-arguments-after-bail.js
@@ -0,0 +1,22 @@
+function outer(fn, x, y) {
+ fn(...arguments);
+}
+
+function inner1(fn, x, y) {
+ assertEq(fn, inner1);
+ assertEq(x, y);
+}
+
+function inner2(fn, x, y) {
+ assertEq(fn, inner2);
+ assertEq(x, 100);
+ assertEq(y, 200);
+}
+
+for (let i = 0; i < 100; i++) {
+ outer(inner1, i, i);
+}
+
+// Call with a different function to cause a bailout. This will lead to
+// recovering the |arguments| object.
+outer(inner2, 100, 200);
diff --git a/js/src/jit-test/tests/arguments/redefine-callee.js b/js/src/jit-test/tests/arguments/redefine-callee.js
new file mode 100644
index 0000000000..c200f5326d
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/redefine-callee.js
@@ -0,0 +1,31 @@
+function test() {
+ let count = 0;
+ for (var i = 0; i < 30; i++) {
+ assertEq(arguments.callee, i > 20 ? 3 : test);
+ if (i === 20) {
+ Object.defineProperty(arguments, "callee", {get: function() { count++; return 3; }});
+ }
+ }
+ assertEq(count, 9);
+}
+test();
+
+function testUnusedResult() {
+ let count = 0;
+ for (var i = 0; i < 30; i++) {
+ arguments.callee;
+ if (i === 20) {
+ Object.defineProperty(arguments, "callee", {get: function() { count++; return 3; }});
+ }
+ }
+ assertEq(count, 9);
+}
+testUnusedResult();
+
+function testSetter() {
+ Object.defineProperty(arguments, "callee", {set: function() {}});
+ for (var i = 0; i < 15; i++) {
+ assertEq(arguments.callee, undefined);
+ }
+}
+testSetter();
diff --git a/js/src/jit-test/tests/arguments/rest-alias-function.js b/js/src/jit-test/tests/arguments/rest-alias-function.js
new file mode 100644
index 0000000000..1dda665210
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-alias-function.js
@@ -0,0 +1,10 @@
+function no_defaults(a, ...rest) {
+ return rest;
+ function rest() { return a; }
+}
+assertEq(typeof no_defaults(), "function");
+function with_defaults(a=42, ...rest) {
+ return rest;
+ function rest() { return a; }
+}
+assertEq(typeof with_defaults(), "function");
diff --git a/js/src/jit-test/tests/arguments/rest-arguments-as-parameters.js b/js/src/jit-test/tests/arguments/rest-arguments-as-parameters.js
new file mode 100644
index 0000000000..120b0ce1c0
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-arguments-as-parameters.js
@@ -0,0 +1,9 @@
+function f1(...arguments) {
+ assertEq("1,2,3", arguments.toString());
+}
+f1(1, 2, 3);
+function f2(arguments, ...rest) {
+ assertEq(arguments, 42);
+ assertEq("1,2,3", rest.toString());
+}
+f2(42, 1, 2, 3); \ No newline at end of file
diff --git a/js/src/jit-test/tests/arguments/rest-basic.js b/js/src/jit-test/tests/arguments/rest-basic.js
new file mode 100644
index 0000000000..cb050d13b3
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-basic.js
@@ -0,0 +1,15 @@
+function check(expected, ...rest) {
+ assertEq(expected.toString(), rest.toString());
+}
+
+assertEq(check.length, 1);
+check([]);
+check(['a', 'b'], 'a', 'b');
+check(['a', 'b', 'c', 'd'], 'a', 'b', 'c', 'd');
+check.apply(null, [['a', 'b'], 'a', 'b'])
+check.call(null, ['a', 'b'], 'a', 'b')
+
+var g = newGlobal();
+g.eval("function f(...rest) { return rest; }");
+var a = g.f(1, 2, 3);
+assertEq(a instanceof g.Array, true); \ No newline at end of file
diff --git a/js/src/jit-test/tests/arguments/rest-bug763954.js b/js/src/jit-test/tests/arguments/rest-bug763954.js
new file mode 100644
index 0000000000..3884abf8e2
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-bug763954.js
@@ -0,0 +1,5 @@
+for (i in ['']) {}
+function f(...patterns) {
+ patterns[i];
+};
+f('');
diff --git a/js/src/jit-test/tests/arguments/rest-debugger.js b/js/src/jit-test/tests/arguments/rest-debugger.js
new file mode 100644
index 0000000000..be9016a07c
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-debugger.js
@@ -0,0 +1,17 @@
+var g = newGlobal({newCompartment: true});
+g.eval("function f(...x) {}");
+var dbg = new Debugger;
+var gw = dbg.addDebuggee(g);
+var fw = gw.getOwnPropertyDescriptor("f").value;
+assertEq(fw.parameterNames.toString(), "x");
+
+var g = newGlobal({newCompartment: true});
+g.eval("function f(...rest) { debugger; }");
+var dbg = Debugger(g);
+dbg.onDebuggerStatement = function (frame) {
+ frame.eval("args = arguments");
+};
+g.f(9, 8, 7);
+
+assertEq(g.args.length, 3);
+assertEq(g.args[2], 7);
diff --git a/js/src/jit-test/tests/arguments/rest-disallow-arguments-strict.js b/js/src/jit-test/tests/arguments/rest-disallow-arguments-strict.js
new file mode 100644
index 0000000000..7f54e5ef7a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-disallow-arguments-strict.js
@@ -0,0 +1,8 @@
+"use strict";
+load(libdir + "asserts.js");
+assertThrowsInstanceOf(function () {
+ eval("(function (...arguments) {})");
+}, SyntaxError);
+assertThrowsInstanceOf(function () {
+ eval("(function (...eval) {})");
+}, SyntaxError);
diff --git a/js/src/jit-test/tests/arguments/rest-in-Function.js b/js/src/jit-test/tests/arguments/rest-in-Function.js
new file mode 100644
index 0000000000..e2966be691
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-in-Function.js
@@ -0,0 +1,3 @@
+h = Function("a", "b", "c", "...rest", "return rest.toString();");
+assertEq(h.length, 3);
+assertEq(h(1, 2, 3, 4, 5), "4,5");
diff --git a/js/src/jit-test/tests/arguments/rest-invalid-syntax.js b/js/src/jit-test/tests/arguments/rest-invalid-syntax.js
new file mode 100644
index 0000000000..f91d93ea62
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-invalid-syntax.js
@@ -0,0 +1,12 @@
+load(libdir + "asserts.js");
+var ieval = eval;
+var offenders = [["..."], ["...rest"," x"], ["...rest", "[x]"],
+ ["...rest", "...rest2"]];
+for (var arglist of offenders) {
+ assertThrowsInstanceOf(function () {
+ ieval("function x(" + arglist.join(", ") + ") {}");
+ }, SyntaxError);
+ assertThrowsInstanceOf(function () {
+ Function.apply(null, arglist.concat("return 0;"));
+ }, SyntaxError);
+} \ No newline at end of file
diff --git a/js/src/jit-test/tests/arguments/rest-nested-arguments.js b/js/src/jit-test/tests/arguments/rest-nested-arguments.js
new file mode 100644
index 0000000000..18f5ca56df
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-nested-arguments.js
@@ -0,0 +1,7 @@
+function f(...rest) {
+ function nested() {
+ return arguments.length;
+ }
+ return nested;
+}
+assertEq(f()(1, 2, 3), 3);
diff --git a/js/src/jit-test/tests/arguments/rest-nested.js b/js/src/jit-test/tests/arguments/rest-nested.js
new file mode 100644
index 0000000000..0ad82e5475
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-nested.js
@@ -0,0 +1,7 @@
+function f(...rest) {
+ function nested () {
+ return rest;
+ }
+ return nested;
+}
+assertEq(f(1, 2, 3)().toString(), [1, 2, 3].toString()); \ No newline at end of file
diff --git a/js/src/jit-test/tests/arguments/rest-underflow.js b/js/src/jit-test/tests/arguments/rest-underflow.js
new file mode 100644
index 0000000000..bb9b39c50b
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-underflow.js
@@ -0,0 +1,9 @@
+function f(a, b, c, ...rest) {
+ assertEq(a, 1);
+ assertEq(b, undefined);
+ assertEq(c, undefined);
+ assertEq(Array.isArray(rest), true);
+ assertEq(rest.length, 0);
+ assertEq(Object.getPrototypeOf(rest), Array.prototype);
+}
+f(1);
diff --git a/js/src/jit-test/tests/arguments/rest-with-arguments.js b/js/src/jit-test/tests/arguments/rest-with-arguments.js
new file mode 100644
index 0000000000..7dfc63c739
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/rest-with-arguments.js
@@ -0,0 +1,40 @@
+// 'arguments' is allowed with rest parameters.
+
+var args;
+
+function restWithArgs(a, b, ...rest) {
+ return arguments;
+}
+
+args = restWithArgs(1, 3, 6, 9);
+assertEq(args.length, 4);
+assertEq(JSON.stringify(args), '{"0":1,"1":3,"2":6,"3":9}');
+
+args = restWithArgs();
+assertEq(args.length, 0);
+
+args = restWithArgs(4, 5);
+assertEq(args.length, 2);
+assertEq(JSON.stringify(args), '{"0":4,"1":5}');
+
+function restWithArgsEval(a, b, ...rest) {
+ return eval("arguments");
+}
+
+args = restWithArgsEval(1, 3, 6, 9);
+assertEq(args.length, 4);
+assertEq(JSON.stringify(args), '{"0":1,"1":3,"2":6,"3":9}');
+
+function g(...rest) {
+ h();
+}
+function h() {
+ g.arguments;
+}
+g();
+
+// eval() is evil, but you can still use it with rest parameters!
+function still_use_eval(...rest) {
+ eval("x = 4");
+}
+still_use_eval();
diff --git a/js/src/jit-test/tests/arguments/slice-args-obj-01.js b/js/src/jit-test/tests/arguments/slice-args-obj-01.js
new file mode 100644
index 0000000000..6d3a826d8e
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/slice-args-obj-01.js
@@ -0,0 +1,19 @@
+function escape(x) { with ({}) {} }
+
+function foo() {
+ escape(arguments);
+ var args = Array.prototype.slice.call(arguments);
+ return bar(args[0], args[1]);
+}
+
+function bar(x, y) {
+ return x + y;
+}
+
+with ({}) {}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1, 2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/slice-args-obj-02.js b/js/src/jit-test/tests/arguments/slice-args-obj-02.js
new file mode 100644
index 0000000000..03581fbdf0
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/slice-args-obj-02.js
@@ -0,0 +1,17 @@
+function foo() {
+ arguments[0] = 3;
+ var args = Array.prototype.slice.call(arguments);
+ return bar(args[0], args[1]);
+}
+
+function bar(x, y) {
+ return x + y;
+}
+
+with ({}) {}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1, 2);
+}
+assertEq(sum, 500);
diff --git a/js/src/jit-test/tests/arguments/slice-args-obj-03.js b/js/src/jit-test/tests/arguments/slice-args-obj-03.js
new file mode 100644
index 0000000000..3205580229
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/slice-args-obj-03.js
@@ -0,0 +1,21 @@
+function escape() { with ({}) {} }
+
+function foo(i) {
+ return i;
+}
+
+function bar(n) {
+ escape(arguments);
+ var args = Array.prototype.slice.call(arguments);
+ return foo(args[0]);
+}
+
+function baz(a, n) {
+ return bar(n);
+}
+
+var sum = 0;
+for (var i = 0; i < 10000; i++) {
+ sum += baz(0, 1);
+}
+assertEq(sum, 10000);
diff --git a/js/src/jit-test/tests/arguments/slice-args-obj-04.js b/js/src/jit-test/tests/arguments/slice-args-obj-04.js
new file mode 100644
index 0000000000..2cddb3351b
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/slice-args-obj-04.js
@@ -0,0 +1,22 @@
+var result;
+
+function g(a, b) {
+ with ({}) {}
+ result = a + b;
+}
+
+function escape() { with({}) {} }
+
+function f() {
+ escape(arguments);
+ for (var i = 0; i < 50; ++i) {
+ var args = Array.prototype.slice.call(arguments);
+ g(args[0], args[1]);
+ }
+}
+
+f(1, 2);
+assertEq(result, 3);
+
+f("");
+assertEq(result, "undefined");
diff --git a/js/src/jit-test/tests/arguments/slice-closed-over-arguments-strict.js b/js/src/jit-test/tests/arguments/slice-closed-over-arguments-strict.js
new file mode 100644
index 0000000000..71815f0b43
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/slice-closed-over-arguments-strict.js
@@ -0,0 +1,17 @@
+"use strict";
+
+function bar(x, y) {
+ return x + y;
+}
+
+function foo(x, y) {
+ function closeOver() { return x; }
+ var args = Array.prototype.slice.call(arguments);
+ return bar(args[0], args[1]);
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1, 2);
+}
+assertEq(sum, 300)
diff --git a/js/src/jit-test/tests/arguments/slice-closed-over-arguments.js b/js/src/jit-test/tests/arguments/slice-closed-over-arguments.js
new file mode 100644
index 0000000000..4a61c4005b
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/slice-closed-over-arguments.js
@@ -0,0 +1,15 @@
+function bar(x, y) {
+ return x + y;
+}
+
+function foo(x, y) {
+ function closeOver() { return x; }
+ var args = Array.prototype.slice.call(arguments);
+ return bar(args[0], args[1]);
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1, 2);
+}
+assertEq(sum, 300)
diff --git a/js/src/jit-test/tests/arguments/slice-redefine-length.js b/js/src/jit-test/tests/arguments/slice-redefine-length.js
new file mode 100644
index 0000000000..9b776064d7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/slice-redefine-length.js
@@ -0,0 +1,19 @@
+function foo() {
+ arguments.length = 2;
+ var args = Array.prototype.slice.call(arguments);
+ return bar(args);
+}
+
+function bar(args) {
+ var result = 0;
+ for (var x of args) {
+ result += x;
+ }
+ return result;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1, 2, 3, 4, 5, 6);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/slice.js b/js/src/jit-test/tests/arguments/slice.js
new file mode 100644
index 0000000000..3ab3d82b67
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/slice.js
@@ -0,0 +1,366 @@
+// Tests when |arguments| are used with Array.prototype.slice.
+
+function testBasic() {
+ // Return the number of arguments.
+ function argslen() { return arguments.length; }
+
+ // Return the first argument.
+ function arg0() { return arguments[0]; }
+
+ // Return the argument at the request index.
+ function argIndex(i) { return arguments[i]; }
+
+ // Call the above functions when no formals are present.
+ function noFormalsLen() { return argslen(...Array.prototype.slice.call(arguments)); }
+ function noFormals0() { return arg0(...Array.prototype.slice.call(arguments)); }
+ function noFormalsIndex() { return argIndex(...Array.prototype.slice.call(arguments)); }
+
+ // Call the above functions when some formals are present.
+ function formalsLen(x, y, z) { return argslen(...Array.prototype.slice.call(arguments)); }
+ function formals0(x, y, z) { return arg0(...Array.prototype.slice.call(arguments)); }
+ function formalsIndex(x, y, z) { return argIndex(...Array.prototype.slice.call(arguments)); }
+
+ // Call the above functions when a rest argument is present.
+ function restLen(...rest) { return argslen(...Array.prototype.slice.call(arguments)); }
+ function rest0(...rest) { return arg0(...Array.prototype.slice.call(arguments)); }
+ function restIndex(...rest) { return argIndex(...Array.prototype.slice.call(arguments)); }
+
+ // Call the above functions when default parameters are present.
+ function defaultLen(x = 0) { return argslen(...Array.prototype.slice.call(arguments)); }
+ function default0(x = 0) { return arg0(...Array.prototype.slice.call(arguments)); }
+ function defaultIndex(x = 0) { return argIndex(...Array.prototype.slice.call(arguments)); }
+
+ for (let i = 0; i < 100; ++i) {
+ assertEq(noFormalsLen(), 0);
+ assertEq(noFormalsLen(1), 1);
+ assertEq(noFormalsLen(1, 2, 3), 3);
+
+ assertEq(formalsLen(), 0);
+ assertEq(formalsLen(1), 1);
+ assertEq(formalsLen(1, 2, 3), 3);
+
+ assertEq(restLen(), 0);
+ assertEq(restLen(1), 1);
+ assertEq(restLen(1, 2, 3), 3);
+
+ assertEq(defaultLen(), 0);
+ assertEq(defaultLen(1), 1);
+ assertEq(defaultLen(1, 2, 3), 3);
+
+ assertEq(noFormals0(), undefined);
+ assertEq(noFormals0(100), 100);
+ assertEq(noFormals0(100, 200, 300), 100);
+
+ assertEq(formals0(), undefined);
+ assertEq(formals0(100), 100);
+ assertEq(formals0(100, 200, 300), 100);
+
+ assertEq(rest0(), undefined);
+ assertEq(rest0(100), 100);
+ assertEq(rest0(100, 200, 300), 100);
+
+ assertEq(default0(), undefined);
+ assertEq(default0(100), 100);
+ assertEq(default0(100, 200, 300), 100);
+
+ assertEq(noFormalsIndex(), undefined);
+ assertEq(noFormalsIndex(0), 0);
+ assertEq(noFormalsIndex(0, 100), 0);
+ assertEq(noFormalsIndex(0, 100, 200, 300), 0);
+ assertEq(noFormalsIndex(1, 100), 100);
+ assertEq(noFormalsIndex(1, 100, 200, 300), 100);
+
+ assertEq(formalsIndex(), undefined);
+ assertEq(formalsIndex(0), 0);
+ assertEq(formalsIndex(0, 100), 0);
+ assertEq(formalsIndex(0, 100, 200, 300), 0);
+ assertEq(formalsIndex(1, 100), 100);
+ assertEq(formalsIndex(1, 100, 200, 300), 100);
+
+ assertEq(restIndex(), undefined);
+ assertEq(restIndex(0), 0);
+ assertEq(restIndex(0, 100), 0);
+ assertEq(restIndex(0, 100, 200, 300), 0);
+ assertEq(restIndex(1, 100), 100);
+ assertEq(restIndex(1, 100, 200, 300), 100);
+
+ assertEq(defaultIndex(), undefined);
+ assertEq(defaultIndex(0), 0);
+ assertEq(defaultIndex(0, 100), 0);
+ assertEq(defaultIndex(0, 100, 200, 300), 0);
+ assertEq(defaultIndex(1, 100), 100);
+ assertEq(defaultIndex(1, 100, 200, 300), 100);
+ }
+}
+testBasic();
+
+// Same as testBasic, except that the first argument is removed.
+function testRemoveFirst() {
+ // Return the number of arguments.
+ function argslen() { return arguments.length; }
+
+ // Return the first argument.
+ function arg0() { return arguments[0]; }
+
+ // Return the argument at the request index.
+ function argIndex(i) { return arguments[i]; }
+
+ // Call the above functions when no formals are present.
+ function noFormalsLen() { return argslen(...Array.prototype.slice.call(arguments, 1)); }
+ function noFormals0() { return arg0(...Array.prototype.slice.call(arguments, 1)); }
+ function noFormalsIndex() { return argIndex(...Array.prototype.slice.call(arguments, 1)); }
+
+ // Call the above functions when some formals are present.
+ function formalsLen(x, y, z) { return argslen(...Array.prototype.slice.call(arguments, 1)); }
+ function formals0(x, y, z) { return arg0(...Array.prototype.slice.call(arguments, 1)); }
+ function formalsIndex(x, y, z) { return argIndex(...Array.prototype.slice.call(arguments, 1)); }
+
+ // Call the above functions when a rest argument is present.
+ function restLen(...rest) { return argslen(...Array.prototype.slice.call(arguments, 1)); }
+ function rest0(...rest) { return arg0(...Array.prototype.slice.call(arguments, 1)); }
+ function restIndex(...rest) { return argIndex(...Array.prototype.slice.call(arguments, 1)); }
+
+ // Call the above functions when default parameters are present.
+ function defaultLen(x = 0) { return argslen(...Array.prototype.slice.call(arguments, 1)); }
+ function default0(x = 0) { return arg0(...Array.prototype.slice.call(arguments, 1)); }
+ function defaultIndex(x = 0) { return argIndex(...Array.prototype.slice.call(arguments, 1)); }
+
+ for (let i = 0; i < 100; ++i) {
+ assertEq(noFormalsLen(), 0);
+ assertEq(noFormalsLen(1), 0);
+ assertEq(noFormalsLen(1, 2, 3), 2);
+
+ assertEq(formalsLen(), 0);
+ assertEq(formalsLen(1), 0);
+ assertEq(formalsLen(1, 2, 3), 2);
+
+ assertEq(restLen(), 0);
+ assertEq(restLen(1), 0);
+ assertEq(restLen(1, 2, 3), 2);
+
+ assertEq(defaultLen(), 0);
+ assertEq(defaultLen(1), 0);
+ assertEq(defaultLen(1, 2, 3), 2);
+
+ assertEq(noFormals0(), undefined);
+ assertEq(noFormals0(100), undefined);
+ assertEq(noFormals0(100, 200, 300), 200);
+
+ assertEq(formals0(), undefined);
+ assertEq(formals0(100), undefined);
+ assertEq(formals0(100, 200, 300), 200);
+
+ assertEq(rest0(), undefined);
+ assertEq(rest0(100), undefined);
+ assertEq(rest0(100, 200, 300), 200);
+
+ assertEq(default0(), undefined);
+ assertEq(default0(100), undefined);
+ assertEq(default0(100, 200, 300), 200);
+
+ assertEq(noFormalsIndex(), undefined);
+ assertEq(noFormalsIndex(0), undefined);
+ assertEq(noFormalsIndex(0, 100), undefined);
+ assertEq(noFormalsIndex(0, 0, 100), 0);
+ assertEq(noFormalsIndex(0, 0, 100, 200, 300), 0);
+ assertEq(noFormalsIndex(0, 1, 100), 100);
+ assertEq(noFormalsIndex(0, 1, 100, 200, 300), 100);
+
+ assertEq(formalsIndex(), undefined);
+ assertEq(formalsIndex(0), undefined);
+ assertEq(formalsIndex(0, 100), undefined);
+ assertEq(formalsIndex(0, 0, 100), 0);
+ assertEq(formalsIndex(0, 0, 100, 200, 300), 0);
+ assertEq(formalsIndex(0, 1, 100), 100);
+ assertEq(formalsIndex(0, 1, 100, 200, 300), 100);
+
+ assertEq(restIndex(), undefined);
+ assertEq(restIndex(0), undefined);
+ assertEq(restIndex(0, 0), 0);
+ assertEq(restIndex(0, 0, 100), 0);
+ assertEq(restIndex(0, 0, 100, 200, 300), 0);
+ assertEq(restIndex(0, 1, 100), 100);
+ assertEq(restIndex(0, 1, 100, 200, 300), 100);
+
+ assertEq(defaultIndex(), undefined);
+ assertEq(defaultIndex(0), undefined);
+ assertEq(defaultIndex(0, 0), 0);
+ assertEq(defaultIndex(0, 0, 100), 0);
+ assertEq(defaultIndex(0, 0, 100, 200, 300), 0);
+ assertEq(defaultIndex(0, 1, 100), 100);
+ assertEq(defaultIndex(0, 1, 100, 200, 300), 100);
+ }
+}
+testRemoveFirst();
+
+// Same as testBasic, except that the last argument is removed.
+function testRemoveLast() {
+ // Return the number of arguments.
+ function argslen() { return arguments.length; }
+
+ // Return the first argument.
+ function arg0() { return arguments[0]; }
+
+ // Return the argument at the request index.
+ function argIndex(i) { return arguments[i]; }
+
+ // Call the above functions when no formals are present.
+ function noFormalsLen() { return argslen(...Array.prototype.slice.call(arguments, 0, -1)); }
+ function noFormals0() { return arg0(...Array.prototype.slice.call(arguments, 0, -1)); }
+ function noFormalsIndex() { return argIndex(...Array.prototype.slice.call(arguments, 0, -1)); }
+
+ // Call the above functions when some formals are present.
+ function formalsLen(x, y, z) { return argslen(...Array.prototype.slice.call(arguments, 0, -1)); }
+ function formals0(x, y, z) { return arg0(...Array.prototype.slice.call(arguments, 0, -1)); }
+ function formalsIndex(x, y, z) { return argIndex(...Array.prototype.slice.call(arguments, 0, -1)); }
+
+ // Call the above functions when a rest argument is present.
+ function restLen(...rest) { return argslen(...Array.prototype.slice.call(arguments, 0, -1)); }
+ function rest0(...rest) { return arg0(...Array.prototype.slice.call(arguments, 0, -1)); }
+ function restIndex(...rest) { return argIndex(...Array.prototype.slice.call(arguments, 0, -1)); }
+
+ // Call the above functions when default parameters are present.
+ function defaultLen(x = 0) { return argslen(...Array.prototype.slice.call(arguments, 0, -1)); }
+ function default0(x = 0) { return arg0(...Array.prototype.slice.call(arguments, 0, -1)); }
+ function defaultIndex(x = 0) { return argIndex(...Array.prototype.slice.call(arguments, 0, -1)); }
+
+ for (let i = 0; i < 100; ++i) {
+ assertEq(noFormalsLen(), 0);
+ assertEq(noFormalsLen(1), 0);
+ assertEq(noFormalsLen(1, 2, 3), 2);
+
+ assertEq(formalsLen(), 0);
+ assertEq(formalsLen(1), 0);
+ assertEq(formalsLen(1, 2, 3), 2);
+
+ assertEq(restLen(), 0);
+ assertEq(restLen(1), 0);
+ assertEq(restLen(1, 2, 3), 2);
+
+ assertEq(defaultLen(), 0);
+ assertEq(defaultLen(1), 0);
+ assertEq(defaultLen(1, 2, 3), 2);
+
+ assertEq(noFormals0(), undefined);
+ assertEq(noFormals0(100), undefined);
+ assertEq(noFormals0(100, 200, 300), 100);
+
+ assertEq(formals0(), undefined);
+ assertEq(formals0(100), undefined);
+ assertEq(formals0(100, 200, 300), 100);
+
+ assertEq(rest0(), undefined);
+ assertEq(rest0(100), undefined);
+ assertEq(rest0(100, 200, 300), 100);
+
+ assertEq(default0(), undefined);
+ assertEq(default0(100), undefined);
+ assertEq(default0(100, 200, 300), 100);
+
+ assertEq(noFormalsIndex(), undefined);
+ assertEq(noFormalsIndex(0), undefined);
+ assertEq(noFormalsIndex(0, 100), 0);
+ assertEq(noFormalsIndex(0, 100, 200, 300), 0);
+ assertEq(noFormalsIndex(1, 100), undefined);
+ assertEq(noFormalsIndex(1, 100, 200, 300), 100);
+
+ assertEq(formalsIndex(), undefined);
+ assertEq(formalsIndex(0), undefined);
+ assertEq(formalsIndex(0, 100), 0);
+ assertEq(formalsIndex(0, 100, 200, 300), 0);
+ assertEq(formalsIndex(1, 100), undefined);
+ assertEq(formalsIndex(1, 100, 200, 300), 100);
+
+ assertEq(restIndex(), undefined);
+ assertEq(restIndex(0), undefined);
+ assertEq(restIndex(0, 100), 0);
+ assertEq(restIndex(0, 100, 200, 300), 0);
+ assertEq(restIndex(1, 100), undefined);
+ assertEq(restIndex(1, 100, 200, 300), 100);
+
+ assertEq(defaultIndex(), undefined);
+ assertEq(defaultIndex(0), undefined);
+ assertEq(defaultIndex(0, 100), 0);
+ assertEq(defaultIndex(0, 100, 200, 300), 0);
+ assertEq(defaultIndex(1, 100), undefined);
+ assertEq(defaultIndex(1, 100, 200, 300), 100);
+ }
+}
+testRemoveLast();
+
+function testOverriddenLength() {
+ function g(x, y = 0) {
+ return x + y;
+ }
+
+ function f(i) {
+ if (i === 100) {
+ arguments.length = 1;
+ }
+ var args = Array.prototype.slice.call(arguments);
+ return g.apply(null, args);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i, i), i !== 100 ? i * 2 : i);
+ }
+}
+testOverriddenLength();
+
+function testOverriddenElement() {
+ function g(x, y) {
+ return x + y;
+ }
+
+ function f(i) {
+ if (i === 100) {
+ arguments[1] = 0;
+ }
+ var args = Array.prototype.slice.call(arguments);
+ return g(args[0], args[1]);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i, i), i !== 100 ? i * 2 : i);
+ }
+}
+testOverriddenElement();
+
+function testDeletedElement() {
+ function g(x, y = 0) {
+ return x + y;
+ }
+
+ function f(i) {
+ if (i === 100) {
+ delete arguments[1];
+ }
+ var args = Array.prototype.slice.call(arguments);
+ return g.apply(null, args);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i, i), i !== 100 ? i * 2 : i);
+ }
+}
+testDeletedElement();
+
+function testForwardedArg() {
+ function g(x, y) {
+ return x + y;
+ }
+
+ function f(i) {
+ function closedOver() {
+ if (i === 100) i = 0;
+ }
+ closedOver();
+ var args = Array.prototype.slice.call(arguments);
+ return g(args[0], args[1]);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i, i), i !== 100 ? i * 2 : i);
+ }
+}
+testForwardedArg();
diff --git a/js/src/jit-test/tests/arguments/spread-args-obj-01.js b/js/src/jit-test/tests/arguments/spread-args-obj-01.js
new file mode 100644
index 0000000000..2528922a4a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/spread-args-obj-01.js
@@ -0,0 +1,18 @@
+function escape(x) { with ({}) {} }
+
+function foo() {
+ escape(arguments);
+ return bar(...arguments);
+}
+
+function bar(x,y) {
+ return x + y;
+}
+
+with ({}) {}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300);
diff --git a/js/src/jit-test/tests/arguments/spread-args-obj-02.js b/js/src/jit-test/tests/arguments/spread-args-obj-02.js
new file mode 100644
index 0000000000..6bb14851c5
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/spread-args-obj-02.js
@@ -0,0 +1,16 @@
+function foo() {
+ arguments[0] = 3;
+ return bar(...arguments);
+}
+
+function bar(x,y) {
+ return x + y;
+}
+
+with ({}) {}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 500);
diff --git a/js/src/jit-test/tests/arguments/spread-args-obj-03.js b/js/src/jit-test/tests/arguments/spread-args-obj-03.js
new file mode 100644
index 0000000000..702884272a
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/spread-args-obj-03.js
@@ -0,0 +1,20 @@
+function escape() { with ({}) {} }
+
+function foo(i) {
+ return i;
+}
+
+function bar(n) {
+ escape(arguments);
+ return foo(...arguments);
+}
+
+function baz(a, n) {
+ return bar(n);
+}
+
+var sum = 0;
+for (var i = 0; i < 10000; i++) {
+ sum += baz(0, 1);
+}
+assertEq(sum, 10000);
diff --git a/js/src/jit-test/tests/arguments/spread-args-obj-04.js b/js/src/jit-test/tests/arguments/spread-args-obj-04.js
new file mode 100644
index 0000000000..b72322a365
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/spread-args-obj-04.js
@@ -0,0 +1,21 @@
+var result;
+
+function g(a, b) {
+ with ({}) {}
+ result = a + b;
+}
+
+function escape() { with({}) {} }
+
+function f() {
+ escape(arguments);
+ for (var i = 0; i < 50; ++i) {
+ g(...arguments);
+ }
+}
+
+f(1, 2);
+assertEq(result, 3);
+
+f("");
+assertEq(result, "undefined");
diff --git a/js/src/jit-test/tests/arguments/spread-call-optimization.js b/js/src/jit-test/tests/arguments/spread-call-optimization.js
new file mode 100644
index 0000000000..5ebc68de36
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/spread-call-optimization.js
@@ -0,0 +1,216 @@
+// Tests when |arguments| are used in optimized spread calls.
+
+function testBasic() {
+ // Return the number of arguments.
+ function argslen() { return arguments.length; }
+
+ // Return the first argument.
+ function arg0() { return arguments[0]; }
+
+ // Return the argument at the request index.
+ function argIndex(i) { return arguments[i]; }
+
+ // Call the above functions when no formals are present.
+ function noFormalsLen() { return argslen(...arguments); }
+ function noFormals0() { return arg0(...arguments); }
+ function noFormalsIndex() { return argIndex(...arguments); }
+
+ // Call the above functions when some formals are present.
+ function formalsLen(x, y, z) { return argslen(...arguments); }
+ function formals0(x, y, z) { return arg0(...arguments); }
+ function formalsIndex(x, y, z) { return argIndex(...arguments); }
+
+ // Call the above functions when a rest argument is present.
+ function restLen(...rest) { return argslen(...arguments); }
+ function rest0(...rest) { return arg0(...arguments); }
+ function restIndex(...rest) { return argIndex(...arguments); }
+
+ // Call the above functions when default parameters are present.
+ function defaultLen(x = 0) { return argslen(...arguments); }
+ function default0(x = 0) { return arg0(...arguments); }
+ function defaultIndex(x = 0) { return argIndex(...arguments); }
+
+ for (let i = 0; i < 100; ++i) {
+ assertEq(noFormalsLen(), 0);
+ assertEq(noFormalsLen(1), 1);
+ assertEq(noFormalsLen(1, 2, 3), 3);
+
+ assertEq(formalsLen(), 0);
+ assertEq(formalsLen(1), 1);
+ assertEq(formalsLen(1, 2, 3), 3);
+
+ assertEq(restLen(), 0);
+ assertEq(restLen(1), 1);
+ assertEq(restLen(1, 2, 3), 3);
+
+ assertEq(defaultLen(), 0);
+ assertEq(defaultLen(1), 1);
+ assertEq(defaultLen(1, 2, 3), 3);
+
+ assertEq(noFormals0(), undefined);
+ assertEq(noFormals0(100), 100);
+ assertEq(noFormals0(100, 200, 300), 100);
+
+ assertEq(formals0(), undefined);
+ assertEq(formals0(100), 100);
+ assertEq(formals0(100, 200, 300), 100);
+
+ assertEq(rest0(), undefined);
+ assertEq(rest0(100), 100);
+ assertEq(rest0(100, 200, 300), 100);
+
+ assertEq(default0(), undefined);
+ assertEq(default0(100), 100);
+ assertEq(default0(100, 200, 300), 100);
+
+ assertEq(noFormalsIndex(), undefined);
+ assertEq(noFormalsIndex(0), 0);
+ assertEq(noFormalsIndex(0, 100), 0);
+ assertEq(noFormalsIndex(0, 100, 200, 300), 0);
+ assertEq(noFormalsIndex(1, 100), 100);
+ assertEq(noFormalsIndex(1, 100, 200, 300), 100);
+
+ assertEq(formalsIndex(), undefined);
+ assertEq(formalsIndex(0), 0);
+ assertEq(formalsIndex(0, 100), 0);
+ assertEq(formalsIndex(0, 100, 200, 300), 0);
+ assertEq(formalsIndex(1, 100), 100);
+ assertEq(formalsIndex(1, 100, 200, 300), 100);
+
+ assertEq(restIndex(), undefined);
+ assertEq(restIndex(0), 0);
+ assertEq(restIndex(0, 100), 0);
+ assertEq(restIndex(0, 100, 200, 300), 0);
+ assertEq(restIndex(1, 100), 100);
+ assertEq(restIndex(1, 100, 200, 300), 100);
+
+ assertEq(defaultIndex(), undefined);
+ assertEq(defaultIndex(0), 0);
+ assertEq(defaultIndex(0, 100), 0);
+ assertEq(defaultIndex(0, 100, 200, 300), 0);
+ assertEq(defaultIndex(1, 100), 100);
+ assertEq(defaultIndex(1, 100, 200, 300), 100);
+ }
+}
+testBasic();
+
+function testOverriddenIterator() {
+ function g(x) {
+ return x;
+ }
+
+ function f(i) {
+ if (i === 100) {
+ arguments[Symbol.iterator] = function() {
+ return ["bad"].values();
+ };
+ }
+ return g(...arguments);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i), i !== 100 ? i : "bad");
+ }
+}
+testOverriddenIterator();
+
+function testOverriddenLength() {
+ function g(x, y = 0) {
+ return x + y;
+ }
+
+ function f(i) {
+ if (i === 100) {
+ arguments.length = 1;
+ }
+ return g(...arguments);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i, i), i !== 100 ? i * 2 : i);
+ }
+}
+testOverriddenLength();
+
+function testOverriddenElement() {
+ function g(x, y) {
+ return x + y;
+ }
+
+ function f(i) {
+ if (i === 100) {
+ arguments[1] = 0;
+ }
+ return g(...arguments);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i, i), i !== 100 ? i * 2 : i);
+ }
+}
+testOverriddenElement();
+
+function testDeletedElement() {
+ function g(x, y = 0) {
+ return x + y;
+ }
+
+ function f(i) {
+ if (i === 100) {
+ delete arguments[1];
+ }
+ return g(...arguments);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i, i), i !== 100 ? i * 2 : i);
+ }
+}
+testDeletedElement();
+
+function testForwardedArg() {
+ function g(x, y) {
+ return x + y;
+ }
+
+ function f(i) {
+ function closedOver() {
+ if (i === 100) i = 0;
+ }
+ closedOver();
+ return g(...arguments);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i, i), i !== 100 ? i * 2 : i);
+ }
+}
+testForwardedArg();
+
+function testModifiedArrayIteratorPrototype() {
+ function g(x, y) {
+ return x + y;
+ }
+
+ const ArrayIteratorPrototype = Reflect.getPrototypeOf([][Symbol.iterator]());
+ const ArrayIteratorPrototypeNext = ArrayIteratorPrototype.next;
+ function newNext() {
+ var result = ArrayIteratorPrototypeNext.call(this);
+ if (!result.done) {
+ result.value *= 2;
+ }
+ return result;
+ }
+
+ function f(i) {
+ if (i === 100) {
+ ArrayIteratorPrototype.next = newNext;
+ }
+ return g(...arguments);
+ }
+
+ for (let i = 0; i <= 150; ++i) {
+ assertEq(f(i, i), i < 100 ? i * 2 : i * 4);
+ }
+}
+testModifiedArrayIteratorPrototype();
diff --git a/js/src/jit-test/tests/arguments/spread-closed-over-arguments-strict.js b/js/src/jit-test/tests/arguments/spread-closed-over-arguments-strict.js
new file mode 100644
index 0000000000..05ce6ec831
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/spread-closed-over-arguments-strict.js
@@ -0,0 +1,15 @@
+'use strict'
+function bar(x,y) {
+ return x + y;
+}
+
+function foo(x, y) {
+ function closeOver() { return x; }
+ return bar(...arguments);
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300)
diff --git a/js/src/jit-test/tests/arguments/spread-closed-over-arguments.js b/js/src/jit-test/tests/arguments/spread-closed-over-arguments.js
new file mode 100644
index 0000000000..15dd800ae3
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/spread-closed-over-arguments.js
@@ -0,0 +1,14 @@
+function bar(x,y) {
+ return x + y;
+}
+
+function foo(x, y) {
+ function closeOver() { return x; }
+ return bar(...arguments);
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2);
+}
+assertEq(sum, 300)
diff --git a/js/src/jit-test/tests/arguments/spread-redefine-length.js b/js/src/jit-test/tests/arguments/spread-redefine-length.js
new file mode 100644
index 0000000000..8c62ddd5d9
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/spread-redefine-length.js
@@ -0,0 +1,18 @@
+function foo() {
+ arguments.length = 2;
+ return bar(...arguments);
+}
+
+function bar() {
+ var result = 0;
+ for (var x of arguments) {
+ result += x;
+ }
+ return result;
+}
+
+var sum = 0;
+for (var i = 0; i < 100; i++) {
+ sum += foo(1,2,3,4,5,6);
+}
+assertEq(sum,300);
diff --git a/js/src/jit-test/tests/arguments/strict-args-flushstack.js b/js/src/jit-test/tests/arguments/strict-args-flushstack.js
new file mode 100644
index 0000000000..257018ba3f
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-args-flushstack.js
@@ -0,0 +1,27 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+var args;
+
+function test()
+{
+ "use strict";
+ eval("args = arguments;");
+ var a = [];
+ for (var i = 0; i < 9; i++)
+ a.push(arguments);
+ return a;
+}
+
+var a = test();
+
+assertEq(Array.isArray(a), true);
+assertEq(a.length, 9);
+
+var count = 0;
+a.forEach(function(v, i) { count++; assertEq(v, args); });
+assertEq(count, 9);
+
+assertEq(Object.prototype.toString.call(args), "[object Arguments]");
+assertEq(args.length, 0);
diff --git a/js/src/jit-test/tests/arguments/strict-args-generator-flushstack.js b/js/src/jit-test/tests/arguments/strict-args-generator-flushstack.js
new file mode 100644
index 0000000000..ecef5dde74
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-args-generator-flushstack.js
@@ -0,0 +1,27 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+var args;
+
+function* upToTen()
+{
+ "use strict";
+ eval("args = arguments;");
+ for (var i = 0; i < 9; i++)
+ yield i;
+}
+
+var gen = upToTen();
+
+var i = 0;
+for (var v of gen)
+{
+ assertEq(v, i);
+ i++;
+}
+
+assertEq(i, 9);
+
+assertEq(Object.prototype.toString.call(args), "[object Arguments]");
+assertEq(args.length, 0);
diff --git a/js/src/jit-test/tests/arguments/strict-args.js b/js/src/jit-test/tests/arguments/strict-args.js
new file mode 100644
index 0000000000..c6d68b2b1f
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-args.js
@@ -0,0 +1,25 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictArgs(a)
+{
+ "use strict";
+ return arguments;
+}
+
+var a1, a2, a3;
+for (var i = 0; i < 9; i++)
+{
+ a1 = strictArgs();
+ a2 = strictArgs(1);
+ a3 = strictArgs(1, obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [1]), true);
+assertEq(arraysEqual(a3, [1, obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-assign-after.js b/js/src/jit-test/tests/arguments/strict-assign-after.js
new file mode 100644
index 0000000000..b295321c3b
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-assign-after.js
@@ -0,0 +1,28 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+var upper;
+function strictAssignAfter(a)
+{
+ "use strict";
+ upper = arguments;
+ a = 42;
+ return upper;
+}
+
+var a1, a2, a3;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictAssignAfter();
+ a2 = strictAssignAfter(17);
+ a3 = strictAssignAfter(obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [17]), true);
+assertEq(arraysEqual(a3, [obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-assign-arguments-element.js b/js/src/jit-test/tests/arguments/strict-assign-arguments-element.js
new file mode 100644
index 0000000000..d2f4f1e5b8
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-assign-arguments-element.js
@@ -0,0 +1,21 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictAssignArgumentsElement(a)
+{
+ "use strict";
+ arguments[0] = 42;
+ return a;
+}
+
+for (var i = 0; i < 5; i++)
+{
+ assertEq(strictAssignArgumentsElement(), undefined);
+ assertEq(strictAssignArgumentsElement(obj), obj);
+ assertEq(strictAssignArgumentsElement(17), 17);
+}
diff --git a/js/src/jit-test/tests/arguments/strict-assign-outer-param-psych.js b/js/src/jit-test/tests/arguments/strict-assign-outer-param-psych.js
new file mode 100644
index 0000000000..6b8fb680eb
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-assign-outer-param-psych.js
@@ -0,0 +1,27 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictAssignOuterParamPSYCH(p)
+{
+ "use strict";
+ function inner(p) { p = 17; }
+ inner();
+ return arguments;
+}
+
+var a1, a2, a3;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictAssignOuterParamPSYCH();
+ a2 = strictAssignOuterParamPSYCH(17);
+ a3 = strictAssignOuterParamPSYCH(obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [17]), true);
+assertEq(arraysEqual(a3, [obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-assign-outer-param.js b/js/src/jit-test/tests/arguments/strict-assign-outer-param.js
new file mode 100644
index 0000000000..f6e4f47675
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-assign-outer-param.js
@@ -0,0 +1,27 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictAssignOuterParam(p)
+{
+ "use strict";
+ function inner() { p = 17; }
+ inner();
+ return arguments;
+}
+
+var a1, a2, a3;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictAssignOuterParam();
+ a2 = strictAssignOuterParam(42);
+ a3 = strictAssignOuterParam(obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [42]), true);
+assertEq(arraysEqual(a3, [obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-assign-parameter-get-element.js b/js/src/jit-test/tests/arguments/strict-assign-parameter-get-element.js
new file mode 100644
index 0000000000..ca283fb9b6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-assign-parameter-get-element.js
@@ -0,0 +1,14 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+function strictAssignParameterGetElement(a)
+{
+ "use strict";
+ a = 17;
+ return arguments[0];
+}
+
+for (var i = 0; i < 5; i++)
+ assertEq(strictAssignParameterGetElement(42), 42);
diff --git a/js/src/jit-test/tests/arguments/strict-assign.js b/js/src/jit-test/tests/arguments/strict-assign.js
new file mode 100644
index 0000000000..6666dec9bb
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-assign.js
@@ -0,0 +1,26 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictAssign(a)
+{
+ "use strict";
+ a = 17;
+ return arguments;
+}
+
+var a1, a2, a3;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictAssign();
+ a2 = strictAssign(1);
+ a3 = strictAssign(1, obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [1]), true);
+assertEq(arraysEqual(a3, [1, obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-eval-mutation.js b/js/src/jit-test/tests/arguments/strict-eval-mutation.js
new file mode 100644
index 0000000000..d33a05c3a0
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-eval-mutation.js
@@ -0,0 +1,24 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictEvalMutation(code)
+{
+ "use strict";
+ return eval(code);
+}
+
+var a1, a2;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictEvalMutation("code = 17; arguments");
+ a2 = strictEvalMutation("arguments[0] = 17; arguments");
+ assertEq(strictEvalMutation("arguments[0] = 17; code"), "arguments[0] = 17; code");
+}
+
+assertEq(arraysEqual(a1, ["code = 17; arguments"]), true);
+assertEq(arraysEqual(a2, [17]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-eval.js b/js/src/jit-test/tests/arguments/strict-eval.js
new file mode 100644
index 0000000000..22ffb7fd85
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-eval.js
@@ -0,0 +1,30 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+function strictEval(code, p)
+{
+ "use strict";
+ eval(code);
+ return arguments;
+}
+
+var a1, a2, a3, a4, a5, a6;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictEval("1", 2);
+ a2 = strictEval("arguments");
+ a3 = strictEval("p = 2");
+ a4 = strictEval("p = 2", 17);
+ a5 = strictEval("arguments[0] = 17");
+ a6 = strictEval("arguments[0] = 17", 42);
+}
+
+assertEq(arraysEqual(a1, ["1", 2]), true);
+assertEq(arraysEqual(a2, ["arguments"]), true);
+assertEq(arraysEqual(a3, ["p = 2"]), true);
+assertEq(arraysEqual(a4, ["p = 2", 17]), true);
+assertEq(arraysEqual(a5, [17]), true);
+assertEq(arraysEqual(a6, [17, 42]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-maybe-assign-outer.js b/js/src/jit-test/tests/arguments/strict-maybe-assign-outer.js
new file mode 100644
index 0000000000..63f9f69248
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-maybe-assign-outer.js
@@ -0,0 +1,26 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictMaybeAssignOuterParam(p)
+{
+ "use strict";
+ function inner() { p = 17; }
+ return arguments;
+}
+
+var a1, a2, a3;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictMaybeAssignOuterParam();
+ a2 = strictMaybeAssignOuterParam(17);
+ a3 = strictMaybeAssignOuterParam(obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [17]), true);
+assertEq(arraysEqual(a3, [obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-maybe-nested-eval.js b/js/src/jit-test/tests/arguments/strict-maybe-nested-eval.js
new file mode 100644
index 0000000000..a1fe88fd35
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-maybe-nested-eval.js
@@ -0,0 +1,26 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+function strictMaybeNestedEval(code, p)
+{
+ "use strict";
+ function inner() { eval(code); }
+ return arguments;
+}
+
+var a1, a2, a3, a4;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictMaybeNestedEval("1", 2);
+ a2 = strictMaybeNestedEval("arguments");
+ a3 = strictMaybeNestedEval("p = 2");
+ a4 = strictMaybeNestedEval("p = 2", 17);
+}
+
+assertEq(arraysEqual(a1, ["1", 2]), true);
+assertEq(arraysEqual(a2, ["arguments"]), true);
+assertEq(arraysEqual(a3, ["p = 2"]), true);
+assertEq(arraysEqual(a4, ["p = 2", 17]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-call.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-call.js
new file mode 100644
index 0000000000..a9430e3247
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-call.js
@@ -0,0 +1,33 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictNestedAssignShadowFunctionCall(p)
+{
+ "use strict";
+ function inner()
+ {
+ function p() { }
+ p = 1776;
+ }
+ inner();
+ return arguments;
+}
+
+var a1, a2, a3, a4;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictNestedAssignShadowFunctionCall();
+ a2 = strictNestedAssignShadowFunctionCall(99);
+ a3 = strictNestedAssignShadowFunctionCall("");
+ a4 = strictNestedAssignShadowFunctionCall(obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [99]), true);
+assertEq(arraysEqual(a3, [""]), true);
+assertEq(arraysEqual(a4, [obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-name.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-name.js
new file mode 100644
index 0000000000..e8ae3177aa
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-name.js
@@ -0,0 +1,33 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictNestedAssignShadowFunctionName(p)
+{
+ "use strict";
+ function inner()
+ {
+ function p() { p = 1776; }
+ p();
+ }
+ inner();
+ return arguments;
+}
+
+var a1, a2, a3, a4, a5;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictNestedAssignShadowFunctionName();
+ a2 = strictNestedAssignShadowFunctionName(99);
+ a3 = strictNestedAssignShadowFunctionName("");
+ a4 = strictNestedAssignShadowFunctionName(obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [99]), true);
+assertEq(arraysEqual(a3, [""]), true);
+assertEq(arraysEqual(a4, [obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function.js
new file mode 100644
index 0000000000..46e0acfd04
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function.js
@@ -0,0 +1,32 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictNestedAssignShadowFunction(p)
+{
+ "use strict";
+ function inner()
+ {
+ function p() { }
+ p = 1776;
+ }
+ return arguments;
+}
+
+var a1, a2, a3, a4;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictNestedAssignShadowFunction();
+ a2 = strictNestedAssignShadowFunction(99);
+ a3 = strictNestedAssignShadowFunction("");
+ a4 = strictNestedAssignShadowFunction(obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [99]), true);
+assertEq(arraysEqual(a3, [""]), true);
+assertEq(arraysEqual(a4, [obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js
new file mode 100644
index 0000000000..03c5e027de
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js
@@ -0,0 +1,39 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictNestedAssignShadowCatchCall(p)
+{
+ "use strict";
+ function inner()
+ {
+ try
+ {
+ }
+ catch (p)
+ {
+ var f = function innermost() { p = 1776; return 12; };
+ f();
+ }
+ }
+ inner();
+ return arguments;
+}
+
+var a1, a2, a3, a4;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictNestedAssignShadowCatchCall();
+ a2 = strictNestedAssignShadowCatchCall(99);
+ a3 = strictNestedAssignShadowCatchCall("");
+ a4 = strictNestedAssignShadowCatchCall(obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [99]), true);
+assertEq(arraysEqual(a3, [""]), true);
+assertEq(arraysEqual(a4, [obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch.js
new file mode 100644
index 0000000000..06df3f9149
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch.js
@@ -0,0 +1,39 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictNestedAssignShadowCatch(p)
+{
+ "use strict";
+ function inner()
+ {
+ try
+ {
+ }
+ catch (p)
+ {
+ var f = function innermost() { p = 1776; return 12; };
+ f();
+ }
+ }
+ return arguments;
+}
+
+var a1, a2, a3, a4;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictNestedAssignShadowCatch();
+ a2 = strictNestedAssignShadowCatch(99);
+ a3 = strictNestedAssignShadowCatch("");
+ a4 = strictNestedAssignShadowCatch(obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [99]), true);
+assertEq(arraysEqual(a3, [""]), true);
+assertEq(arraysEqual(a4, [obj]), true);
+
diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-var.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-var.js
new file mode 100644
index 0000000000..8248bed338
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-var.js
@@ -0,0 +1,29 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+/********************
+ * STRICT ARGUMENTS *
+ ********************/
+
+function strictNestedAssignShadowVar(p)
+{
+ "use strict";
+ function inner()
+ {
+ var p = 12;
+ function innermost() { p = 1776; return 12; }
+ return innermost();
+ }
+ return arguments;
+}
+
+assertEq(arraysEqual(strictNestedAssignShadowVar(), []), true);
+assertEq(arraysEqual(strictNestedAssignShadowVar(99), [99]), true);
+assertEq(arraysEqual(strictNestedAssignShadowVar(""), [""]), true);
+assertEq(arraysEqual(strictNestedAssignShadowVar(obj), [obj]), true);
+
diff --git a/js/src/jit-test/tests/arguments/strict-nested-eval.js b/js/src/jit-test/tests/arguments/strict-nested-eval.js
new file mode 100644
index 0000000000..1f6eab54e4
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-nested-eval.js
@@ -0,0 +1,31 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+function strictNestedEval(code, p)
+{
+ "use strict";
+ function inner() { eval(code); }
+ inner();
+ return arguments;
+}
+
+var a1, a2, a3, a4, a5, a6;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictNestedEval("1", 2);
+ a2 = strictNestedEval("arguments");
+ a3 = strictNestedEval("p = 2");
+ a4 = strictNestedEval("p = 2", 17);
+ a5 = strictNestedEval("arguments[0] = 17");
+ a6 = strictNestedEval("arguments[0] = 17", 42);
+}
+
+assertEq(arraysEqual(a1, ["1", 2]), true);
+assertEq(arraysEqual(a2, ["arguments"]), true);
+assertEq(arraysEqual(a3, ["p = 2"]), true);
+assertEq(arraysEqual(a4, ["p = 2", 17]), true);
+assertEq(arraysEqual(a5, ["arguments[0] = 17"]), true);
+assertEq(arraysEqual(a6, ["arguments[0] = 17", 42]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js b/js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js
new file mode 100644
index 0000000000..d80b7be0a7
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js
@@ -0,0 +1,30 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+function strictNestedShadowEval(code, p)
+{
+ "use strict";
+ function inner(p) { eval(code); }
+ return arguments;
+}
+
+var a1, a2, a3, a4, a5, a6;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictNestedShadowEval("1", 2);
+ a2 = strictNestedShadowEval("arguments");
+ a3 = strictNestedShadowEval("p = 2");
+ a4 = strictNestedShadowEval("p = 2", 17);
+ a5 = strictNestedShadowEval("arguments[0] = 17");
+ a6 = strictNestedShadowEval("arguments[0] = 17", 42);
+}
+
+assertEq(arraysEqual(a1, ["1", 2]), true);
+assertEq(arraysEqual(a2, ["arguments"]), true);
+assertEq(arraysEqual(a3, ["p = 2"]), true);
+assertEq(arraysEqual(a4, ["p = 2", 17]), true);
+assertEq(arraysEqual(a5, ["arguments[0] = 17"]), true);
+assertEq(arraysEqual(a6, ["arguments[0] = 17", 42]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js b/js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js
new file mode 100644
index 0000000000..cf9edea9ee
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js
@@ -0,0 +1,30 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+function strictNestedShadowMaybeEval(code, p)
+{
+ "use strict";
+ function inner(p) { eval(code); }
+ return arguments;
+}
+
+var a1, a2, a3, a4, a5, a6;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictNestedShadowMaybeEval("1", 2);
+ a2 = strictNestedShadowMaybeEval("arguments");
+ a3 = strictNestedShadowMaybeEval("p = 2");
+ a4 = strictNestedShadowMaybeEval("p = 2", 17);
+ a5 = strictNestedShadowMaybeEval("arguments[0] = 17");
+ a6 = strictNestedShadowMaybeEval("arguments[0] = 17", 42);
+}
+
+assertEq(arraysEqual(a1, ["1", 2]), true);
+assertEq(arraysEqual(a2, ["arguments"]), true);
+assertEq(arraysEqual(a3, ["p = 2"]), true);
+assertEq(arraysEqual(a4, ["p = 2", 17]), true);
+assertEq(arraysEqual(a5, ["arguments[0] = 17"]), true);
+assertEq(arraysEqual(a6, ["arguments[0] = 17", 42]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-noargs.js b/js/src/jit-test/tests/arguments/strict-noargs.js
new file mode 100644
index 0000000000..dfee3c8583
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-noargs.js
@@ -0,0 +1,25 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+load(libdir + 'array-compare.js');
+
+var obj = {};
+
+function strictNoargs()
+{
+ "use strict";
+ return arguments;
+}
+
+var a1, a2, a3;
+for (var i = 0; i < 5; i++)
+{
+ a1 = strictNoargs();
+ a2 = strictNoargs(1);
+ a3 = strictNoargs(1, obj);
+}
+
+assertEq(arraysEqual(a1, []), true);
+assertEq(arraysEqual(a2, [1]), true);
+assertEq(arraysEqual(a3, [1, obj]), true);
diff --git a/js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js b/js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js
new file mode 100644
index 0000000000..5c193b99f6
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js
@@ -0,0 +1,13 @@
+
+"use strict";
+
+function loop(a) {
+ a = arguments.length;
+ var result = 0;
+ for (var i = 0; i < 5000; i++) {
+ result += a;
+ }
+ return result;
+}
+
+assertEq(loop(11), 5000);
diff --git a/js/src/jit-test/tests/arguments/testDelArg1.js b/js/src/jit-test/tests/arguments/testDelArg1.js
new file mode 100644
index 0000000000..a6b5eee326
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/testDelArg1.js
@@ -0,0 +1,13 @@
+function f(x,y,z) {
+ z = 9;
+ delete arguments[2];
+ assertEq(arguments[2], undefined);
+ o = arguments;
+ assertEq(o[2], undefined);
+ assertEq(o[2] == undefined, true);
+}
+
+for (var i = 0; i < 10; ++i) {
+ print(i);
+ f(1,2,3)
+}
diff --git a/js/src/jit-test/tests/arguments/testDelArg2.js b/js/src/jit-test/tests/arguments/testDelArg2.js
new file mode 100644
index 0000000000..09fcf1f57d
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/testDelArg2.js
@@ -0,0 +1,13 @@
+function f(del) {
+ o = arguments;
+ if (del)
+ delete o[2];
+ for (var i = 0; i < 10; ++i)
+ assertEq(o[2] == undefined, del);
+}
+
+// record without arg deleted
+f(false, 1,2,3,4);
+
+// run with arg deleted
+f(true, 1,2,3,4);
diff --git a/js/src/jit-test/tests/arguments/testDelArg3.js b/js/src/jit-test/tests/arguments/testDelArg3.js
new file mode 100644
index 0000000000..4931870bbc
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/testDelArg3.js
@@ -0,0 +1,42 @@
+function assertGood(x) {
+ assertEq(x, "good");
+}
+
+(function() {
+ var a = arguments;
+ return function() {
+ assertGood.apply(null, a);
+ }
+})("good")();
+
+(function() {
+ var a = arguments;
+ return function() {
+ a[0] = "good";
+ assertGood.apply(null, a);
+ }
+})("bad")();
+
+Object.prototype[0] = "good";
+
+(function() {
+ var a = arguments;
+ return function() {
+ delete a[0];
+ assertGood.apply(null, a);
+ }
+})("bad")();
+
+delete Object.prototype[0];
+
+function assertUndefined(x) {
+ assertEq(x, undefined);
+}
+
+(function() {
+ var a = arguments;
+ return function() {
+ a[0] = "bad";
+ assertUndefined.apply(null, a);
+ }
+})()();
diff --git a/js/src/jit-test/tests/arguments/testDelArg3Strict.js b/js/src/jit-test/tests/arguments/testDelArg3Strict.js
new file mode 100644
index 0000000000..77d247a4d8
--- /dev/null
+++ b/js/src/jit-test/tests/arguments/testDelArg3Strict.js
@@ -0,0 +1,44 @@
+"use strict";
+
+function assertGood(x) {
+ assertEq(x, "good");
+}
+
+(function() {
+ var a = arguments;
+ return function() {
+ assertGood.apply(null, a);
+ }
+})("good")();
+
+(function() {
+ var a = arguments;
+ return function() {
+ a[0] = "good";
+ assertGood.apply(null, a);
+ }
+})("bad")();
+
+Object.prototype[0] = "good";
+
+(function() {
+ var a = arguments;
+ return function() {
+ delete a[0];
+ assertGood.apply(null, a);
+ }
+})("bad")();
+
+delete Object.prototype[0];
+
+function assertUndefined(x) {
+ assertEq(x, undefined);
+}
+
+(function() {
+ var a = arguments;
+ return function() {
+ a[0] = "bad";
+ assertUndefined.apply(null, a);
+ }
+})()();