author | André Bargull <andre.bargull@gmail.com> |
Thu, 14 Oct 2021 17:59:55 +0000 (2021-10-14) | |
changeset 595927 | e419b06ed3d4aa53276a42ebc162813c0b266dc6 |
parent 595926 | 0b43bb2f2d8be40b5a89034ce78a8e3ba4a9513f |
child 595928 | a490916980ca489866c40bb8f1771d9bb29a5d59 |
push id | 38880 |
push user | nerli@mozilla.com |
push date | Fri, 15 Oct 2021 09:50:04 +0000 (2021-10-15) |
treeherder | mozilla-central@bb0faec6af52 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 725966 |
milestone | 95.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/warp/typeof-switch.js @@ -0,0 +1,78 @@ +// Test case |typeof| folding in switch-statement contexts. + +function TypeOf(thing) { + switch (typeof thing) { + case "undefined": + return "undefined"; + case "object": + return "object"; + case "function": + return "function"; + case "string": + return "string"; + case "number": + return "number"; + case "boolean": + return "boolean"; + case "symbol": + return "symbol"; + case "bigint": + return "bigint"; + case "bad": + return "bad"; + } + return "bad2"; +} + +function test() { + const ccwGlobal = newGlobal({newCompartment: true}); + const xs = [ + // "undefined" + // Plain undefined and objects emulating undefined, including various + // proxy wrapper cases. + undefined, + createIsHTMLDDA(), + wrapWithProto(createIsHTMLDDA(), null), + ccwGlobal.eval("createIsHTMLDDA()"), + + // "object" + // Plain objects and various proxy wrapper cases. + {}, + this, + new Proxy({}, {}), + wrapWithProto({}, null), + transplantableObject({proxy: true}).object, + ccwGlobal.Object(), + + // "function" + // Plain functions and various proxy wrapper cases. + function(){}, + new Proxy(function(){}, {}), + new Proxy(createIsHTMLDDA(), {}), + wrapWithProto(function(){}, null), + ccwGlobal.Function(), + + // "string" + "", + + // "number" + // Int32 and Double numbers. + 0, + 1.23, + + // "boolean" + true, + + // "symbol" + Symbol(), + + // "bigint" + 0n, + ]; + + for (let i = 0; i < 500; ++i) { + let x = xs[i % xs.length]; + assertEq(TypeOf(x), typeof x); + } +} +for (let i = 0; i < 2; ++i) test();
--- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -4087,16 +4087,32 @@ bool MCompare::evaluateConstantOperands( *result = FoldComparison(jsop_, lhs->numberToDouble(), rhs->numberToDouble()); return true; } return false; } +MDefinition* MCompare::tryFoldTypeOf(TempAllocator& alloc) { + auto typeOfPair = IsTypeOfCompare(this); + if (!typeOfPair) { + return this; + } + auto [typeOfName, type] = *typeOfPair; + auto* typeOf = typeOfName->input()->toTypeOf(); + + MOZ_ASSERT(type != JSTYPE_LIMIT, "unknown typeof strings folded earlier"); + + MConstant* cst = MConstant::New(alloc, Int32Value(type)); + block()->insertBefore(this, cst); + + return MCompare::New(alloc, typeOf, cst, jsop(), MCompare::Compare_Int32); +} + MDefinition* MCompare::tryFoldCharCompare(TempAllocator& alloc) { if (compareType() != Compare_String) { return this; } MDefinition* left = lhs(); MOZ_ASSERT(left->type() == MIRType::String); @@ -4202,16 +4218,20 @@ MDefinition* MCompare::foldsTo(TempAlloc if (type() == MIRType::Int32) { return MConstant::New(alloc, Int32Value(result)); } MOZ_ASSERT(type() == MIRType::Boolean); return MConstant::New(alloc, BooleanValue(result)); } + if (MDefinition* folded = tryFoldTypeOf(alloc); folded != this) { + return folded; + } + if (MDefinition* folded = tryFoldCharCompare(alloc); folded != this) { return folded; } if (MDefinition* folded = tryFoldStringCompare(alloc); folded != this) { return folded; }
--- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -2636,16 +2636,17 @@ class MCompare : public MBinaryInstructi } #endif ALLOW_CLONE(MCompare) private: [[nodiscard]] bool tryFoldEqualOperands(bool* result); [[nodiscard]] bool tryFoldTypeOf(bool* result); + [[nodiscard]] MDefinition* tryFoldTypeOf(TempAllocator& alloc); [[nodiscard]] MDefinition* tryFoldCharCompare(TempAllocator& alloc); [[nodiscard]] MDefinition* tryFoldStringCompare(TempAllocator& alloc); public: bool congruentTo(const MDefinition* ins) const override { if (!binaryCongruentTo(ins)) { return false; }