blob: 69725525d679c681c86390d9560cd767ec02501e [file] [log] [blame]
//@ skip if $architecture == "x86"
var createBuiltin = $vm.createBuiltin;
// This is pretty bad but I need a private name.
var putFuncToPrivateName = createBuiltin(`(function (func) { @arrayIteratorIsDone = func })`)
putFuncToPrivateName(function (a,b) { return b; })
function createTailCallForwardingFuncWith(body, thisValue) {
return createBuiltin(`(function (a) {
"use strict";
${body}
return @tailCallForwardArguments(@arrayIteratorIsDone, ${thisValue});
})`);
}
var foo = createTailCallForwardingFuncWith("", "@undefined");
function baz() {
return foo.call(true, 7);
}
noInline(baz);
var fooNoInline = createTailCallForwardingFuncWith("", "@undefined");
noInline(foo);
for (let i = 0; i < 100000; i++) {
if (baz.call() !== undefined)
throw new Error(i);
if (fooNoInline.call(undefined, 3) !== undefined)
throw new Error(i);
}
putFuncToPrivateName(function () { "use strict"; return { thisValue: this, argumentsValue: arguments}; });
var foo2 = createTailCallForwardingFuncWith("", "this");
var fooNI2 = createTailCallForwardingFuncWith("", "this");
noInline(fooNI2);
function baz2() {
return foo2.call(true, 7);
}
noInline(baz2);
for (let i = 0; i < 100000; i++) {
let result = foo2.call(true, 7);
if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7)
throw new Error(i);
result = baz2.call();
if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7)
throw new Error(i);
result = fooNI2.call(true, 7);
if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7)
throw new Error(i);
}
putFuncToPrivateName(function () { "use strict"; return this; });
var foo3 = createTailCallForwardingFuncWith("", "{ thisValue: this, otherValue: 'hello'} ");
var fooNI3 = createTailCallForwardingFuncWith("", "{ thisValue: this, otherValue: 'hello'} ");
noInline(fooNI3);
function baz3() {
return foo3.call(true, 7);
}
noInline(baz3);
for (let i = 0; i < 100000; i++) {
let result = foo3.call(true, 7);
if (result.thisValue !== true)
throw new Error(i);
result = baz3.call();
if (result.thisValue !== true)
throw new Error(i);
result = fooNI3.call(true, 7);
if (result.thisValue !== true)
throw new Error(i);
}
putFuncToPrivateName(function () { "use strict"; return this; });
let bodyText = `
for (let i = 0; i < 100; i++) {
if (a + i === 100)
return a;
}
`;
var foo4 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
var fooNI4 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
noInline(fooNI4);
function baz4() {
return foo4.call(true, 0);
}
noInline(baz4);
for (let i = 0; i < 100000; i++) {
let result = foo4.call(true, 0);
if (result.thisValue !== true || result.otherValue !== "hello")
throw new Error(i);
result = baz4.call();
if (result.thisValue !== true || result.otherValue !== "hello")
throw new Error(i);
result = fooNI4.call(true, 0);
if (result.thisValue !== true || result.otherValue !== "hello")
throw new Error(i);
result = fooNI4.call(true, 1);
if (result !== 1)
throw new Error(i);
result = fooNI4.call(true, "");
if (result.thisValue !== true || result.otherValue !== "hello")
throw new Error(i);
}
var testFunc = function () { "use strict"; return this; }
noInline(testFunc);
putFuncToPrivateName(testFunc);
var foo5 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
var fooNI5 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
noInline(fooNI5);
function baz5() {
return foo5.call(true, 0);
}
noInline(baz5);
for (let i = 0; i < 100000; i++) {
let result = foo5.call(true, 0);
if (result.thisValue !== true || result.otherValue !== "hello")
throw new Error(i);
result = baz5.call();
if (result.thisValue !== true || result.otherValue !== "hello")
throw new Error(i);
result = fooNI5.call(true, 0);
if (result.thisValue !== true || result.otherValue !== "hello")
throw new Error(i);
result = fooNI5.call(true, 1);
if (result !== 1)
throw new Error(i);
result = fooNI5.call(true, "");
if (result.thisValue !== true || result.otherValue !== "hello")
throw new Error(i);
}
putFuncToPrivateName(function() { return arguments; });
var foo6 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
function baz6() {
"use strict"
return foo6.apply(this, arguments);
}
noInline(baz6);
function arrayEq(a, b) {
if (a.length !== b.length)
throw new Error();
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i])
throw new Error();
}
}
let args = ["a", {}, [], Symbol(), 1, 1.234, undefined, null];
for (let i = 0; i < 100000; i++) {
let result = baz6.apply(undefined, args);
arrayEq(result, args);
}