Bug 1850305 part 2 - Add some infallible type conversions in the transpiler. r=iain

This fixes issues caught by the assertion added in the next patch. These operations
are actually infallible so didn't have the same performance cliff.

Differential Revision: https://phabricator.services.mozilla.com/D187265
This commit is contained in:
Jan de Mooij 2023-09-06 12:53:11 +00:00
Родитель 9f755e8bd8
Коммит 7831d3edd1
5 изменённых файлов: 44 добавлений и 4 удалений

Просмотреть файл

@ -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();

Просмотреть файл

@ -1695,6 +1695,7 @@ bool WarpBuilder::build_EndIter(BytecodeLocation loc) {
bool WarpBuilder::build_CloseIter(BytecodeLocation loc) { bool WarpBuilder::build_CloseIter(BytecodeLocation loc) {
MDefinition* iter = current->pop(); MDefinition* iter = current->pop();
iter = unboxObjectInfallible(iter);
return buildIC(loc, CacheKind::CloseIter, {iter}); return buildIC(loc, CacheKind::CloseIter, {iter});
} }
@ -2901,6 +2902,10 @@ bool WarpBuilder::build_SpreadCall(BytecodeLocation loc) {
CallInfo callInfo(alloc(), constructing, loc.resultIsPopped()); CallInfo callInfo(alloc(), constructing, loc.resultIsPopped());
callInfo.initForSpreadCall(current); 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<WarpCacheIR>(loc)) { if (auto* cacheIRSnapshot = getOpSnapshot<WarpCacheIR>(loc)) {
return transpileCall(loc, cacheIRSnapshot, &callInfo); return transpileCall(loc, cacheIRSnapshot, &callInfo);
} }
@ -2921,6 +2926,10 @@ bool WarpBuilder::build_SpreadNew(BytecodeLocation loc) {
CallInfo callInfo(alloc(), constructing, loc.resultIsPopped()); CallInfo callInfo(alloc(), constructing, loc.resultIsPopped());
callInfo.initForSpreadCall(current); 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<WarpCacheIR>(loc)) { if (auto* cacheIRSnapshot = getOpSnapshot<WarpCacheIR>(loc)) {
return transpileCall(loc, cacheIRSnapshot, &callInfo); return transpileCall(loc, cacheIRSnapshot, &callInfo);
} }

Просмотреть файл

@ -51,6 +51,18 @@ void WarpBuilderShared::pushConstant(const Value& v) {
current->push(cst); 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, MCall* WarpBuilderShared::makeCall(CallInfo& callInfo, bool needsThisCheck,
WrappedFunction* target, bool isDOMCall) { WrappedFunction* target, bool isDOMCall) {
auto addUndefined = [this]() -> MConstant* { auto addUndefined = [this]() -> MConstant* {
@ -73,9 +85,10 @@ MInstruction* WarpBuilderShared::makeSpreadCall(CallInfo& callInfo,
current->add(elements); current->add(elements);
if (callInfo.constructing()) { if (callInfo.constructing()) {
auto* newTarget = unboxObjectInfallible(callInfo.getNewTarget());
auto* construct = auto* construct =
MConstructArray::New(alloc(), target, callInfo.callee(), elements, MConstructArray::New(alloc(), target, callInfo.callee(), elements,
callInfo.thisArg(), callInfo.getNewTarget()); callInfo.thisArg(), newTarget);
if (isSameRealm) { if (isSameRealm) {
construct->setNotCrossRealm(); construct->setNotCrossRealm();
} }

Просмотреть файл

@ -420,6 +420,8 @@ class WarpBuilderShared {
MConstant* constant(const JS::Value& v); MConstant* constant(const JS::Value& v);
void pushConstant(const JS::Value& v); void pushConstant(const JS::Value& v);
MDefinition* unboxObjectInfallible(MDefinition* def);
MCall* makeCall(CallInfo& callInfo, bool needsThisCheck, MCall* makeCall(CallInfo& callInfo, bool needsThisCheck,
WrappedFunction* target = nullptr, bool isDOMCall = false); WrappedFunction* target = nullptr, bool isDOMCall = false);
MInstruction* makeSpreadCall(CallInfo& callInfo, bool needsThisCheck, MInstruction* makeSpreadCall(CallInfo& callInfo, bool needsThisCheck,

Просмотреть файл

@ -3853,7 +3853,10 @@ bool WarpCacheIRTranspiler::emitTypedArrayByteLengthDoubleResult(
auto* size = MTypedArrayElementSize::New(alloc(), obj); auto* size = MTypedArrayElementSize::New(alloc(), obj);
add(size); 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); mul->setCanBeNegativeZero(false);
add(mul); add(mul);
@ -4949,7 +4952,7 @@ bool WarpCacheIRTranspiler::maybeCreateThis(MDefinition* callee,
MOZ_ASSERT(thisArg->type() == MIRType::MagicIsConstructing || MOZ_ASSERT(thisArg->type() == MIRType::MagicIsConstructing ||
thisArg->isPhi()); thisArg->isPhi());
MDefinition* newTarget = callInfo_->getNewTarget(); auto* newTarget = unboxObjectInfallible(callInfo_->getNewTarget());
auto* createThis = MCreateThis::New(alloc(), callee, newTarget); auto* createThis = MCreateThis::New(alloc(), callee, newTarget);
add(createThis); add(createThis);
@ -5310,7 +5313,8 @@ bool WarpCacheIRTranspiler::emitCallBoundScriptedFunction(
auto* boundArgs = MLoadFixedSlot::New( auto* boundArgs = MLoadFixedSlot::New(
alloc(), callee, BoundFunctionObject::firstInlineBoundArgSlot()); alloc(), callee, BoundFunctionObject::firstInlineBoundArgSlot());
add(boundArgs); add(boundArgs);
elements = MElements::New(alloc(), boundArgs); auto* boundArgsObj = unboxObjectInfallible(boundArgs);
elements = MElements::New(alloc(), boundArgsObj);
add(elements); add(elements);
} }