summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/ion/recover-rest.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/ion/recover-rest.js')
-rw-r--r--js/src/jit-test/tests/ion/recover-rest.js340
1 files changed, 340 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/ion/recover-rest.js b/js/src/jit-test/tests/ion/recover-rest.js
new file mode 100644
index 0000000000..11bfde7ff4
--- /dev/null
+++ b/js/src/jit-test/tests/ion/recover-rest.js
@@ -0,0 +1,340 @@
+// Prevent GC from cancelling/discarding Ion compilations.
+gczeal(0);
+
+// This function is used to force a bailout when it is inlined, and to recover
+// the frame which is inlining this function.
+var resumeHere = function (i) { if (i >= 99) bailout(); };
+
+// This function is used to cause an invalidation after having removed a branch
+// after DCE. This is made to check if we correctly recover an array
+// allocation.
+var uceFault = function (i) {
+ if (i > 98)
+ uceFault = function (i) { return true; };
+ return false;
+};
+
+function empty() {}
+
+var globalArgs;
+function escape(args) { globalArgs = args; }
+
+// Check rest array length.
+function length(i, ...rest) {
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function lengthBail(i, ...rest) {
+ resumeHere(i);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+// Check rest array content.
+function content(...rest) {
+ assertEq(rest[0], rest[1]);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function contentBail(...rest) {
+ resumeHere(rest[0]);
+ assertEq(rest[0], rest[1]);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function contentExtraFormals(i, ...rest) {
+ assertEq(rest[0], i);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+function contentExtraFormalsBail(i, ...rest) {
+ resumeHere(i);
+ assertEq(rest[0], i);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+// No scalar replacement when the rest array is modified.
+function setLength(i, ...rest) {
+ rest.length = 0;
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+function setLengthBail(i, ...rest) {
+ resumeHere(i);
+ rest.length = 0;
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+function setContent(i, ...rest) {
+ rest[0] = "bad";
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+function setContentBail(i, ...rest) {
+ resumeHere(i);
+ rest[0] = "bad";
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+function deleteContent(i, ...rest) {
+ delete rest[0];
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+function deleteContentBail(i, ...rest) {
+ resumeHere(i);
+ delete rest[0];
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+// No scalar replacement when the rest array escapes.
+function escapes(i, ...rest) {
+ escape(rest);
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+function escapesBail(i, ...rest) {
+ resumeHere(i);
+ escape(rest);
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+// Check rest array with Function.prototype.apply.
+function apply(...rest) {
+ empty.apply(null, rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function applyBail(...rest) {
+ resumeHere(rest[0]);
+ empty.apply(null, rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function applyExtraFormals(i, ...rest) {
+ empty.apply(null, rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function applyExtraFormalsBail(i, ...rest) {
+ resumeHere(i);
+ empty.apply(null, rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+// Check rest array with spread.
+function spread(...rest) {
+ empty(...rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function spreadBail(...rest) {
+ resumeHere(rest[0]);
+ empty(...rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function spreadExtraFormals(i, ...rest) {
+ empty(...rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function spreadExtraFormalsBail(i, ...rest) {
+ resumeHere(i);
+ empty(...rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+// Extra args currently not supported.
+function spreadExtraArgs(...rest) {
+ empty(0, ...rest);
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+function spreadExtraArgsBail(...rest) {
+ resumeHere(rest[0]);
+ empty(0, ...rest);
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+// Check rest array with new spread.
+function newSpread(...rest) {
+ new empty(...rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function newSpreadBail(...rest) {
+ resumeHere(rest[0]);
+ new empty(...rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function newSpreadExtraFormals(i, ...rest) {
+ new empty(...rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function newSpreadExtraFormalsBail(i, ...rest) {
+ resumeHere(i);
+ new empty(...rest);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+// Extra args currently not supported.
+function newSpreadExtraArgs(...rest) {
+ new empty(0, ...rest);
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+function newSpreadExtraArgsBail(...rest) {
+ resumeHere(rest[0]);
+ new empty(0, ...rest);
+ assertRecoveredOnBailout(rest, false);
+ return rest.length;
+}
+
+// The arguments object isn't mapped.
+function setArgs(i, ...rest) {
+ arguments[1] = "fail";
+ assertEq(rest[0], i);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+function setArgsBail(i, ...rest) {
+ resumeHere(i);
+ arguments[1] = "fail";
+ assertEq(rest[0], i);
+ assertRecoveredOnBailout(rest, true);
+ return rest.length;
+}
+
+// Check that we correctly allocate the array after taking the recover path.
+var uceFault_recoverLength = eval(`(${uceFault})`.replace('uceFault', 'uceFault_recoverLength'));
+function recoverLength(i, ...rest) {
+ if (uceFault_recoverLength(i) || uceFault_recoverLength(i)) {
+ return rest.length;
+ }
+ assertRecoveredOnBailout(rest, true);
+ return 0;
+}
+
+var uceFault_recoverContent = eval(`(${uceFault})`.replace('uceFault', 'uceFault_recoverContent'));
+function recoverContent(i, ...rest) {
+ if (uceFault_recoverContent(i) || uceFault_recoverContent(i)) {
+ return rest[0];
+ }
+ assertRecoveredOnBailout(rest, true);
+ return 0;
+}
+
+var uceFault_recoverApply = eval(`(${uceFault})`.replace('uceFault', 'uceFault_recoverApply'));
+function recoverApply(i, ...rest) {
+ if (uceFault_recoverApply(i) || uceFault_recoverApply(i)) {
+ return empty.apply(null, rest);
+ }
+ assertRecoveredOnBailout(rest, true);
+ return 0;
+}
+
+var uceFault_recoverSpread = eval(`(${uceFault})`.replace('uceFault', 'uceFault_recoverSpread'));
+function recoverSpread(i, ...rest) {
+ if (uceFault_recoverSpread(i) || uceFault_recoverSpread(i)) {
+ return empty(...rest);
+ }
+ assertRecoveredOnBailout(rest, true);
+ return 0;
+}
+
+var uceFault_recoverNewSpread = eval(`(${uceFault})`.replace('uceFault', 'uceFault_recoverNewSpread'));
+function recoverNewSpread(i, ...rest) {
+ if (uceFault_recoverNewSpread(i) || uceFault_recoverNewSpread(i)) {
+ return new empty(...rest);
+ }
+ assertRecoveredOnBailout(rest, true);
+ return 0;
+}
+
+var uceFault_recoverSetArgs = eval(`(${uceFault})`.replace('uceFault', 'uceFault_recoverSetArgs'));
+function recoverSetArgs(i, ...rest) {
+ arguments[1] = "fail";
+ if (uceFault_recoverSetArgs(i) || uceFault_recoverSetArgs(i)) {
+ // Ensure arguments[1] isn't mapped to rest[0].
+ assertEq(rest[0], "ok");
+ return 0;
+ }
+ assertRecoveredOnBailout(rest, true);
+ return 0;
+}
+
+// Prevent compilation of the top-level
+eval(`(${resumeHere})`);
+
+for (let i = 0; i < 100; i++) {
+ length(i);
+ lengthBail(i);
+ content(i, i);
+ contentBail(i, i);
+ contentExtraFormals(i, i);
+ contentExtraFormalsBail(i, i);
+ setLength(i);
+ setLengthBail(i);
+ setContent(i, i);
+ setContentBail(i, i);
+ deleteContent(i, i);
+ deleteContentBail(i, i);
+ escapes(i);
+ escapesBail(i);
+ apply(i);
+ applyBail(i);
+ applyExtraFormals(i);
+ applyExtraFormalsBail(i);
+ spread(i);
+ spreadBail(i);
+ spreadExtraFormals(i);
+ spreadExtraFormalsBail(i);
+ spreadExtraArgs(i);
+ spreadExtraArgsBail(i);
+ newSpread(i);
+ newSpreadBail(i);
+ newSpreadExtraFormals(i);
+ newSpreadExtraFormalsBail(i);
+ newSpreadExtraArgs(i);
+ newSpreadExtraArgsBail(i);
+ setArgs(i, i);
+ setArgsBail(i, i);
+
+ recoverLength(i);
+ recoverContent(i);
+ recoverApply(i);
+ recoverSpread(i);
+ recoverNewSpread(i);
+ recoverSetArgs(i, "ok");
+}