diff --git a/js/src/jit-test/tests/cacheir/spread-minmax-5.js b/js/src/jit-test/tests/cacheir/spread-minmax-5.js new file mode 100644 index 000000000000..a787f16783e1 --- /dev/null +++ b/js/src/jit-test/tests/cacheir/spread-minmax-5.js @@ -0,0 +1,12 @@ +function f() { + var arr = [[]]; + for (var i = 1; i < 101; i++) { + arr[0].push(i); + } + var res = 0; + for (var i = 0; i < 100; i++) { + res += Math.max(...arr[0]) + Math.min(...arr[0]); + } + assertEq(res, 10100); +} +f(); diff --git a/js/src/jit/WarpBuilder.cpp b/js/src/jit/WarpBuilder.cpp index 023542da1990..6f289205830d 100644 --- a/js/src/jit/WarpBuilder.cpp +++ b/js/src/jit/WarpBuilder.cpp @@ -1695,6 +1695,7 @@ bool WarpBuilder::build_EndIter(BytecodeLocation loc) { bool WarpBuilder::build_CloseIter(BytecodeLocation loc) { MDefinition* iter = current->pop(); + iter = unboxObjectInfallible(iter); return buildIC(loc, CacheKind::CloseIter, {iter}); } @@ -2901,6 +2902,10 @@ bool WarpBuilder::build_SpreadCall(BytecodeLocation loc) { CallInfo callInfo(alloc(), constructing, loc.resultIsPopped()); callInfo.initForSpreadCall(current); + // The argument must be an array object. + MOZ_ASSERT(callInfo.argc() == 1); + callInfo.setArg(0, unboxObjectInfallible(callInfo.getArg(0))); + if (auto* cacheIRSnapshot = getOpSnapshot(loc)) { return transpileCall(loc, cacheIRSnapshot, &callInfo); } @@ -2921,6 +2926,10 @@ bool WarpBuilder::build_SpreadNew(BytecodeLocation loc) { CallInfo callInfo(alloc(), constructing, loc.resultIsPopped()); callInfo.initForSpreadCall(current); + // The argument must be an array object. + MOZ_ASSERT(callInfo.argc() == 1); + callInfo.setArg(0, unboxObjectInfallible(callInfo.getArg(0))); + if (auto* cacheIRSnapshot = getOpSnapshot(loc)) { return transpileCall(loc, cacheIRSnapshot, &callInfo); } diff --git a/js/src/jit/WarpBuilderShared.cpp b/js/src/jit/WarpBuilderShared.cpp index 50d25e628aa4..36a1e85927db 100644 --- a/js/src/jit/WarpBuilderShared.cpp +++ b/js/src/jit/WarpBuilderShared.cpp @@ -51,6 +51,18 @@ void WarpBuilderShared::pushConstant(const Value& v) { current->push(cst); } +MDefinition* WarpBuilderShared::unboxObjectInfallible(MDefinition* def) { + if (def->type() == MIRType::Object) { + return def; + } + + MOZ_ASSERT(def->type() == MIRType::Value); + + auto* unbox = MUnbox::New(alloc(), def, MIRType::Object, MUnbox::Infallible); + current->add(unbox); + return unbox; +} + MCall* WarpBuilderShared::makeCall(CallInfo& callInfo, bool needsThisCheck, WrappedFunction* target, bool isDOMCall) { auto addUndefined = [this]() -> MConstant* { @@ -73,9 +85,10 @@ MInstruction* WarpBuilderShared::makeSpreadCall(CallInfo& callInfo, current->add(elements); if (callInfo.constructing()) { + auto* newTarget = unboxObjectInfallible(callInfo.getNewTarget()); auto* construct = MConstructArray::New(alloc(), target, callInfo.callee(), elements, - callInfo.thisArg(), callInfo.getNewTarget()); + callInfo.thisArg(), newTarget); if (isSameRealm) { construct->setNotCrossRealm(); } diff --git a/js/src/jit/WarpBuilderShared.h b/js/src/jit/WarpBuilderShared.h index 4dd0c57d553d..84644114cd20 100644 --- a/js/src/jit/WarpBuilderShared.h +++ b/js/src/jit/WarpBuilderShared.h @@ -420,6 +420,8 @@ class WarpBuilderShared { MConstant* constant(const JS::Value& v); void pushConstant(const JS::Value& v); + MDefinition* unboxObjectInfallible(MDefinition* def); + MCall* makeCall(CallInfo& callInfo, bool needsThisCheck, WrappedFunction* target = nullptr, bool isDOMCall = false); MInstruction* makeSpreadCall(CallInfo& callInfo, bool needsThisCheck, diff --git a/js/src/jit/WarpCacheIRTranspiler.cpp b/js/src/jit/WarpCacheIRTranspiler.cpp index 0189ccb1de63..f1e706aaa023 100644 --- a/js/src/jit/WarpCacheIRTranspiler.cpp +++ b/js/src/jit/WarpCacheIRTranspiler.cpp @@ -3853,7 +3853,10 @@ bool WarpCacheIRTranspiler::emitTypedArrayByteLengthDoubleResult( auto* size = MTypedArrayElementSize::New(alloc(), obj); add(size); - auto* mul = MMul::New(alloc(), lengthDouble, size, MIRType::Double); + auto* sizeDouble = MToDouble::New(alloc(), size); + add(sizeDouble); + + auto* mul = MMul::New(alloc(), lengthDouble, sizeDouble, MIRType::Double); mul->setCanBeNegativeZero(false); add(mul); @@ -4949,7 +4952,7 @@ bool WarpCacheIRTranspiler::maybeCreateThis(MDefinition* callee, MOZ_ASSERT(thisArg->type() == MIRType::MagicIsConstructing || thisArg->isPhi()); - MDefinition* newTarget = callInfo_->getNewTarget(); + auto* newTarget = unboxObjectInfallible(callInfo_->getNewTarget()); auto* createThis = MCreateThis::New(alloc(), callee, newTarget); add(createThis); @@ -5310,7 +5313,8 @@ bool WarpCacheIRTranspiler::emitCallBoundScriptedFunction( auto* boundArgs = MLoadFixedSlot::New( alloc(), callee, BoundFunctionObject::firstInlineBoundArgSlot()); add(boundArgs); - elements = MElements::New(alloc(), boundArgs); + auto* boundArgsObj = unboxObjectInfallible(boundArgs); + elements = MElements::New(alloc(), boundArgsObj); add(elements); }