blob: e4e92c49d47fae672e17e9f9ef4f17242422f17a [file] [log] [blame]
"use strict"
// Trivial cases: everything is monomorphic and super predictable.
function compareConstants()
{
return (null == null) && (null == undefined) && (undefined == null);
}
noInline(compareConstants);
for (let i = 0; i < 1e4; ++i) {
if (!compareConstants())
throw "Failed to compareConstants().";
}
function opaqueNull() {
return null;
}
noInline(opaqueNull);
function opaqueUndefined() {
return undefined;
}
noInline(opaqueUndefined);
function compareConstantsAndDynamicValues()
{
return ((null == opaqueNull())
&& (opaqueNull() == null)
&& (undefined == opaqueNull())
&& (opaqueNull() == undefined)
&& (null == opaqueUndefined())
&& (opaqueUndefined() == null)
&& (undefined == opaqueUndefined())
&& (opaqueUndefined() == undefined));
}
noInline(compareConstantsAndDynamicValues);
for (let i = 1e4; i--;) {
if (!compareConstantsAndDynamicValues())
throw "Failed compareConstantsAndDynamicValues()";
}
function compareDynamicValues()
{
return ((opaqueNull() == opaqueNull())
&& (opaqueUndefined() == opaqueUndefined())
&& (opaqueNull() == opaqueUndefined())
&& (opaqueUndefined() == opaqueNull()));
}
noInline(compareDynamicValues);
for (let i = 0; i < 1e4; ++i) {
if (!compareDynamicValues())
throw "Failed compareDynamicValues()";
}
function compareDynamicValueToItself()
{
const value1 = opaqueNull();
const value2 = opaqueUndefined();
return value1 == value1 && value2 == value2;
}
noInline(compareDynamicValueToItself);
for (let i = 0; i < 1e4; ++i) {
if (!compareDynamicValueToItself())
throw "Failed compareDynamicValueToItself()";
}
// The case that interested us in the first place.
// Accessing an array with undecided shape always return undefined.
function arrayTesting()
{
let returnValue = true;
const array1 = new Array(2);
for (let i = 0; i < 3; ++i) {
returnValue = returnValue && (array1[i] == null);
returnValue = returnValue && (null == array1[i]);
returnValue = returnValue && (array1[i] == undefined);
returnValue = returnValue && (undefined == array1[i]);
}
const array2 = new Array(2);
for (let i = 0; i < 2; ++i) {
returnValue = returnValue && (array2[i] == opaqueNull());
returnValue = returnValue && (opaqueNull() == array2[i]);
returnValue = returnValue && (array2[i] == opaqueUndefined());
returnValue = returnValue && (opaqueUndefined() == array2[i]);
}
const array3 = new Array(2);
for (let i = 0; i < 3; ++i) {
returnValue = returnValue && (array3[i] == array3[i]);
returnValue = returnValue && (array1[i] == array3[i]);
returnValue = returnValue && (array3[i] == array1[i]);
returnValue = returnValue && (array2[i] == array3[i]);
returnValue = returnValue && (array3[i] == array2[i]);
}
return returnValue;
}
noInline(arrayTesting);
for (let i = 0; i < 1e4; ++i) {
if (!arrayTesting())
throw "Failed arrayTesting()";
}
// Let's make it polymorphic after optimization. We should fallback to a generic compare operation.
function opaqueCompare1(a, b) {
return a == b;
}
noInline(opaqueCompare1);
function testNullComparatorUpdate() {
for (let i = 0; i < 1e4; ++i) {
if (!opaqueCompare1(null, null))
throw "Failed opaqueCompare1(null, null)"
}
// Let's change types
for (let i = 0; i < 1e4; ++i) {
if (opaqueCompare1("foo", null))
throw "Failed opaqueCompare1(\"foo\", null)"
}
}
testNullComparatorUpdate();
function opaqueCompare2(a, b) {
return a == b;
}
noInline(opaqueCompare2);
function testUndefinedComparatorUpdate() {
for (let i = 0; i < 1e4; ++i) {
if (!opaqueCompare2(undefined, undefined))
throw "Failed opaqueCompare2(undefined, undefined)"
}
// Let's change types
for (let i = 0; i < 1e4; ++i) {
if (!opaqueCompare2("bar", "bar"))
throw "Failed opaqueCompare2(\"bar\", \"bar\")"
}
}
testUndefinedComparatorUpdate();
function opaqueCompare3(a, b) {
return a == b;
}
noInline(opaqueCompare3);
function testNullAndUndefinedComparatorUpdate() {
for (let i = 0; i < 1e4; ++i) {
if (!opaqueCompare3(undefined, null) || !opaqueCompare2(null, undefined))
throw "Failed opaqueCompare2(undefined/null, undefined/null)"
}
// Let's change types
for (let i = 0; i < 1e4; ++i) {
if (opaqueCompare3(undefined, "bar"))
throw "Failed opaqueCompare3(undefined, \"bar\")"
}
}
testNullAndUndefinedComparatorUpdate();