зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1445235 part 1 - Also add Spectre mitigations for MBoundsCheck added for stores. r=luke
--HG-- extra : rebase_source : b1ead63e2c8934e7b9a6da722196f242e784a2f8
This commit is contained in:
Родитель
d9a734332c
Коммит
2ac711d172
|
@ -7893,8 +7893,7 @@ bool
|
|||
IonBuilder::checkTypedObjectIndexInBounds(uint32_t elemSize,
|
||||
MDefinition* index,
|
||||
TypedObjectPrediction objPrediction,
|
||||
LinearSum* indexAsByteOffset,
|
||||
BoundsCheckKind kind)
|
||||
LinearSum* indexAsByteOffset)
|
||||
{
|
||||
// Ensure index is an integer.
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), index);
|
||||
|
@ -7921,7 +7920,7 @@ IonBuilder::checkTypedObjectIndexInBounds(uint32_t elemSize,
|
|||
return false;
|
||||
}
|
||||
|
||||
index = addBoundsCheck(idInt32, length, kind);
|
||||
index = addBoundsCheck(idInt32, length);
|
||||
|
||||
return indexAsByteOffset->add(index, AssertedCast<int32_t>(elemSize));
|
||||
}
|
||||
|
@ -7941,11 +7940,8 @@ IonBuilder::getElemTryScalarElemOfTypedObject(bool* emitted,
|
|||
MOZ_ASSERT(elemSize == ScalarTypeDescr::alignment(elemType));
|
||||
|
||||
LinearSum indexAsByteOffset(alloc());
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset,
|
||||
BoundsCheckKind::IsLoad))
|
||||
{
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset))
|
||||
return Ok();
|
||||
}
|
||||
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
|
@ -7966,11 +7962,8 @@ IonBuilder::getElemTryReferenceElemOfTypedObject(bool* emitted,
|
|||
uint32_t elemSize = ReferenceTypeDescr::size(elemType);
|
||||
|
||||
LinearSum indexAsByteOffset(alloc());
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset,
|
||||
BoundsCheckKind::IsLoad))
|
||||
{
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset))
|
||||
return Ok();
|
||||
}
|
||||
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
|
@ -8090,11 +8083,8 @@ IonBuilder::getElemTryComplexElemOfTypedObject(bool* emitted,
|
|||
MDefinition* elemTypeObj = typeObjectForElementFromArrayStructType(type);
|
||||
|
||||
LinearSum indexAsByteOffset(alloc());
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset,
|
||||
BoundsCheckKind::IsLoad))
|
||||
{
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset))
|
||||
return Ok();
|
||||
}
|
||||
|
||||
return pushDerivedTypedObject(emitted, obj, indexAsByteOffset,
|
||||
elemPrediction, elemTypeObj);
|
||||
|
@ -8385,7 +8375,7 @@ IonBuilder::getElemTryString(bool* emitted, MDefinition* obj, MDefinition* index
|
|||
MStringLength* length = MStringLength::New(alloc(), obj);
|
||||
current->add(length);
|
||||
|
||||
index = addBoundsCheck(index, length, BoundsCheckKind::IsLoad);
|
||||
index = addBoundsCheck(index, length);
|
||||
|
||||
MCharCodeAt* charCode = MCharCodeAt::New(alloc(), obj, index);
|
||||
current->add(charCode);
|
||||
|
@ -8427,7 +8417,7 @@ IonBuilder::getElemTryArguments(bool* emitted, MDefinition* obj, MDefinition* in
|
|||
index = idInt32;
|
||||
|
||||
// Bailouts if we read more than the number of actual arguments.
|
||||
index = addBoundsCheck(index, length, BoundsCheckKind::IsLoad);
|
||||
index = addBoundsCheck(index, length);
|
||||
|
||||
// Load the argument from the actual arguments.
|
||||
bool modifiesArgs = script()->baselineScript()->modifiesArguments();
|
||||
|
@ -8515,8 +8505,7 @@ IonBuilder::getElemTryArgumentsInlinedIndex(bool* emitted, MDefinition* obj, MDe
|
|||
// cannot re-enter because reading out of bounds arguments will disable the
|
||||
// lazy arguments optimization for this script, when this code would be
|
||||
// executed in Baseline. (see GetElemOptimizedArguments)
|
||||
index = addBoundsCheck(index, constantInt(inlineCallInfo_->argc()),
|
||||
BoundsCheckKind::IsLoad);
|
||||
index = addBoundsCheck(index, constantInt(inlineCallInfo_->argc()));
|
||||
|
||||
// Get an instruction to represent the state of the argument vector.
|
||||
MInstruction* args = MArgumentState::New(alloc().fallible(), inlineCallInfo_->argv());
|
||||
|
@ -8709,7 +8698,7 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index)
|
|||
// in-bounds elements, and the array is packed or its holes are not
|
||||
// read. This is the best case: we can separate the bounds check for
|
||||
// hoisting.
|
||||
index = addBoundsCheck(index, initLength, BoundsCheckKind::IsLoad);
|
||||
index = addBoundsCheck(index, initLength);
|
||||
|
||||
load = MLoadElement::New(alloc(), elements, index, needsHoleCheck, loadDouble);
|
||||
current->add(load);
|
||||
|
@ -8748,8 +8737,7 @@ void
|
|||
IonBuilder::addTypedArrayLengthAndData(MDefinition* obj,
|
||||
BoundsChecking checking,
|
||||
MDefinition** index,
|
||||
MInstruction** length, MInstruction** elements,
|
||||
BoundsCheckKind boundsCheckKind)
|
||||
MInstruction** length, MInstruction** elements)
|
||||
{
|
||||
MOZ_ASSERT((index != nullptr) == (elements != nullptr));
|
||||
|
||||
|
@ -8783,7 +8771,7 @@ IonBuilder::addTypedArrayLengthAndData(MDefinition* obj,
|
|||
|
||||
if (index) {
|
||||
if (checking == DoBoundsCheck)
|
||||
*index = addBoundsCheck(*index, *length, boundsCheckKind);
|
||||
*index = addBoundsCheck(*index, *length);
|
||||
|
||||
*elements = MConstantElements::New(alloc(), data);
|
||||
current->add(*elements);
|
||||
|
@ -8798,7 +8786,7 @@ IonBuilder::addTypedArrayLengthAndData(MDefinition* obj,
|
|||
|
||||
if (index) {
|
||||
if (checking == DoBoundsCheck)
|
||||
*index = addBoundsCheck(*index, *length, boundsCheckKind);
|
||||
*index = addBoundsCheck(*index, *length);
|
||||
|
||||
*elements = MTypedArrayElements::New(alloc(), obj);
|
||||
current->add(*elements);
|
||||
|
@ -8880,8 +8868,7 @@ IonBuilder::jsop_getelem_typed(MDefinition* obj, MDefinition* index,
|
|||
// Get length, bounds-check, then get elements, and add all instructions.
|
||||
MInstruction* length;
|
||||
MInstruction* elements;
|
||||
addTypedArrayLengthAndData(obj, DoBoundsCheck, &index, &length, &elements,
|
||||
BoundsCheckKind::IsLoad);
|
||||
addTypedArrayLengthAndData(obj, DoBoundsCheck, &index, &length, &elements);
|
||||
|
||||
// Load the element.
|
||||
MLoadUnboxedScalar* load = MLoadUnboxedScalar::New(alloc(), elements, index, arrayType);
|
||||
|
@ -9066,11 +9053,8 @@ IonBuilder::setElemTryReferenceElemOfTypedObject(bool* emitted,
|
|||
uint32_t elemSize = ReferenceTypeDescr::size(elemType);
|
||||
|
||||
LinearSum indexAsByteOffset(alloc());
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset,
|
||||
BoundsCheckKind::IsStore))
|
||||
{
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset))
|
||||
return Ok();
|
||||
}
|
||||
|
||||
return setPropTryReferenceTypedObjectValue(emitted, obj, indexAsByteOffset,
|
||||
elemType, value, nullptr);
|
||||
|
@ -9090,11 +9074,8 @@ IonBuilder::setElemTryScalarElemOfTypedObject(bool* emitted,
|
|||
MOZ_ASSERT(elemSize == ScalarTypeDescr::alignment(elemType));
|
||||
|
||||
LinearSum indexAsByteOffset(alloc());
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset,
|
||||
BoundsCheckKind::IsStore))
|
||||
{
|
||||
if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset))
|
||||
return Ok();
|
||||
}
|
||||
|
||||
return setPropTryScalarTypedObjectValue(emitted, obj, indexAsByteOffset, elemType, value);
|
||||
}
|
||||
|
@ -9389,7 +9370,7 @@ IonBuilder::initOrSetElemDense(TemporaryTypeSet::DoubleConversion conversion,
|
|||
} else {
|
||||
MInstruction* initLength = initializedLength(elements);
|
||||
|
||||
id = addBoundsCheck(id, initLength, BoundsCheckKind::IsStore);
|
||||
id = addBoundsCheck(id, initLength);
|
||||
bool needsHoleCheck = !packed && hasExtraIndexedProperty;
|
||||
|
||||
MStoreElement* ins = MStoreElement::New(alloc(), elements, id, newValue, needsHoleCheck);
|
||||
|
@ -9437,8 +9418,7 @@ IonBuilder::jsop_setelem_typed(Scalar::Type arrayType,
|
|||
MInstruction* length;
|
||||
MInstruction* elements;
|
||||
BoundsChecking checking = expectOOB ? SkipBoundsCheck : DoBoundsCheck;
|
||||
addTypedArrayLengthAndData(obj, checking, &id, &length, &elements,
|
||||
BoundsCheckKind::IsStore);
|
||||
addTypedArrayLengthAndData(obj, checking, &id, &length, &elements);
|
||||
|
||||
// Clamp value to [0, 255] for Uint8ClampedArray.
|
||||
MDefinition* toWrite = value;
|
||||
|
@ -12977,7 +12957,7 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id)
|
|||
|
||||
// If there are no holes, speculate the InArray check will not fail.
|
||||
if (!needsHoleCheck && !failedBoundsCheck_) {
|
||||
addBoundsCheck(idInt32, initLength, BoundsCheckKind::UnusedIndex);
|
||||
addBoundsCheck(idInt32, initLength);
|
||||
pushConstant(BooleanValue(true));
|
||||
return Ok();
|
||||
}
|
||||
|
@ -13322,7 +13302,7 @@ IonBuilder::addMaybeCopyElementsForWrite(MDefinition* object, bool checkNative)
|
|||
}
|
||||
|
||||
MInstruction*
|
||||
IonBuilder::addBoundsCheck(MDefinition* index, MDefinition* length, BoundsCheckKind kind)
|
||||
IonBuilder::addBoundsCheck(MDefinition* index, MDefinition* length)
|
||||
{
|
||||
MInstruction* check = MBoundsCheck::New(alloc(), index, length);
|
||||
current->add(check);
|
||||
|
@ -13331,7 +13311,20 @@ IonBuilder::addBoundsCheck(MDefinition* index, MDefinition* length, BoundsCheckK
|
|||
if (failedBoundsCheck_)
|
||||
check->setNotMovable();
|
||||
|
||||
if (kind == BoundsCheckKind::IsLoad && JitOptions.spectreIndexMasking) {
|
||||
if (JitOptions.spectreIndexMasking) {
|
||||
// Use a separate MIR instruction for the index masking. Doing this as
|
||||
// part of MBoundsCheck would be unsound because bounds checks can be
|
||||
// optimized or eliminated completely. Consider this:
|
||||
//
|
||||
// for (var i = 0; i < x; i++)
|
||||
// res = arr[i];
|
||||
//
|
||||
// If we can prove |x < arr.length|, we are able to eliminate the bounds
|
||||
// check, but we should not get rid of the index masking because the
|
||||
// |i < x| branch could still be mispredicted.
|
||||
//
|
||||
// Using a separate instruction lets us eliminate the bounds check
|
||||
// without affecting the index masking.
|
||||
check = MSpectreMaskIndex::New(alloc(), check, length);
|
||||
current->add(check);
|
||||
}
|
||||
|
|
|
@ -199,8 +199,7 @@ class IonBuilder
|
|||
MInstruction* addConvertElementsToDoubles(MDefinition* elements);
|
||||
MDefinition* addMaybeCopyElementsForWrite(MDefinition* object, bool checkNative);
|
||||
|
||||
enum class BoundsCheckKind { IsLoad, IsStore, UnusedIndex };
|
||||
MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length, BoundsCheckKind kind);
|
||||
MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length);
|
||||
|
||||
MInstruction* addShapeGuard(MDefinition* obj, Shape* const shape, BailoutKind bailoutKind);
|
||||
MInstruction* addGroupGuard(MDefinition* obj, ObjectGroup* group, BailoutKind bailoutKind);
|
||||
|
@ -379,8 +378,7 @@ class IonBuilder
|
|||
bool checkTypedObjectIndexInBounds(uint32_t elemSize,
|
||||
MDefinition* index,
|
||||
TypedObjectPrediction objTypeDescrs,
|
||||
LinearSum* indexAsByteOffset,
|
||||
BoundsCheckKind kind);
|
||||
LinearSum* indexAsByteOffset);
|
||||
AbortReasonOr<Ok> pushDerivedTypedObject(bool* emitted,
|
||||
MDefinition* obj,
|
||||
const LinearSum& byteOffset,
|
||||
|
@ -468,16 +466,14 @@ class IonBuilder
|
|||
void addTypedArrayLengthAndData(MDefinition* obj,
|
||||
BoundsChecking checking,
|
||||
MDefinition** index,
|
||||
MInstruction** length, MInstruction** elements,
|
||||
BoundsCheckKind boundsCheckKind);
|
||||
MInstruction** length, MInstruction** elements);
|
||||
|
||||
// Add an instruction to compute a typed array's length to the current
|
||||
// block. If you also need the typed array's data, use the above method
|
||||
// instead.
|
||||
MInstruction* addTypedArrayLength(MDefinition* obj) {
|
||||
MInstruction* length;
|
||||
addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr,
|
||||
BoundsCheckKind::UnusedIndex);
|
||||
addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr);
|
||||
return length;
|
||||
}
|
||||
|
||||
|
@ -773,7 +769,7 @@ class IonBuilder
|
|||
|
||||
bool prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType,
|
||||
MInstruction** elements, MDefinition** index,
|
||||
Scalar::Type* arrayType, BoundsCheckKind boundsCheckKind);
|
||||
Scalar::Type* arrayType);
|
||||
InliningResult inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
unsigned numElems);
|
||||
InliningResult inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
|
@ -839,8 +835,7 @@ class IonBuilder
|
|||
bool atomicsMeetsPreconditions(CallInfo& callInfo, Scalar::Type* arrayElementType,
|
||||
bool* requiresDynamicCheck,
|
||||
AtomicCheckResult checkResult=DoCheckAtomicResult);
|
||||
void atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index,
|
||||
BoundsCheckKind kind);
|
||||
void atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index);
|
||||
|
||||
bool testNeedsArgumentCheck(JSFunction* target, CallInfo& callInfo);
|
||||
|
||||
|
|
|
@ -1871,7 +1871,7 @@ IonBuilder::inlineStrCharCodeAt(CallInfo& callInfo)
|
|||
MStringLength* length = MStringLength::New(alloc(), callInfo.thisArg());
|
||||
current->add(length);
|
||||
|
||||
index = addBoundsCheck(index, length, BoundsCheckKind::IsLoad);
|
||||
index = addBoundsCheck(index, length);
|
||||
|
||||
MCharCodeAt* charCode = MCharCodeAt::New(alloc(), callInfo.thisArg(), index);
|
||||
current->add(charCode);
|
||||
|
@ -1981,7 +1981,7 @@ IonBuilder::inlineStrCharAt(CallInfo& callInfo)
|
|||
MStringLength* length = MStringLength::New(alloc(), callInfo.thisArg());
|
||||
current->add(length);
|
||||
|
||||
index = addBoundsCheck(index, length, BoundsCheckKind::IsLoad);
|
||||
index = addBoundsCheck(index, length);
|
||||
|
||||
// String.charAt(x) = String.fromCharCode(String.charCodeAt(x))
|
||||
MCharCodeAt* charCode = MCharCodeAt::New(alloc(), callInfo.thisArg(), index);
|
||||
|
@ -3324,7 +3324,7 @@ IonBuilder::inlineAtomicsCompareExchange(CallInfo& callInfo)
|
|||
|
||||
MInstruction* elements;
|
||||
MDefinition* index;
|
||||
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsLoad);
|
||||
atomicsCheckBounds(callInfo, &elements, &index);
|
||||
|
||||
if (requiresCheck)
|
||||
addSharedTypedArrayGuard(callInfo.getArg(0));
|
||||
|
@ -3360,7 +3360,7 @@ IonBuilder::inlineAtomicsExchange(CallInfo& callInfo)
|
|||
|
||||
MInstruction* elements;
|
||||
MDefinition* index;
|
||||
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsLoad);
|
||||
atomicsCheckBounds(callInfo, &elements, &index);
|
||||
|
||||
if (requiresCheck)
|
||||
addSharedTypedArrayGuard(callInfo.getArg(0));
|
||||
|
@ -3392,7 +3392,7 @@ IonBuilder::inlineAtomicsLoad(CallInfo& callInfo)
|
|||
|
||||
MInstruction* elements;
|
||||
MDefinition* index;
|
||||
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsLoad);
|
||||
atomicsCheckBounds(callInfo, &elements, &index);
|
||||
|
||||
if (requiresCheck)
|
||||
addSharedTypedArrayGuard(callInfo.getArg(0));
|
||||
|
@ -3444,7 +3444,7 @@ IonBuilder::inlineAtomicsStore(CallInfo& callInfo)
|
|||
|
||||
MInstruction* elements;
|
||||
MDefinition* index;
|
||||
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsStore);
|
||||
atomicsCheckBounds(callInfo, &elements, &index);
|
||||
|
||||
if (requiresCheck)
|
||||
addSharedTypedArrayGuard(callInfo.getArg(0));
|
||||
|
@ -3488,7 +3488,7 @@ IonBuilder::inlineAtomicsBinop(CallInfo& callInfo, InlinableNative target)
|
|||
|
||||
MInstruction* elements;
|
||||
MDefinition* index;
|
||||
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsLoad);
|
||||
atomicsCheckBounds(callInfo, &elements, &index);
|
||||
|
||||
AtomicOp k = AtomicFetchAddOp;
|
||||
switch (target) {
|
||||
|
@ -3585,15 +3585,14 @@ IonBuilder::atomicsMeetsPreconditions(CallInfo& callInfo, Scalar::Type* arrayTyp
|
|||
}
|
||||
|
||||
void
|
||||
IonBuilder::atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index,
|
||||
BoundsCheckKind kind)
|
||||
IonBuilder::atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index)
|
||||
{
|
||||
// Perform bounds checking and extract the elements vector.
|
||||
MDefinition* obj = callInfo.getArg(0);
|
||||
MInstruction* length = nullptr;
|
||||
*index = callInfo.getArg(1);
|
||||
*elements = nullptr;
|
||||
addTypedArrayLengthAndData(obj, DoBoundsCheck, index, &length, elements, kind);
|
||||
addTypedArrayLengthAndData(obj, DoBoundsCheck, index, &length, elements);
|
||||
}
|
||||
|
||||
IonBuilder::InliningResult
|
||||
|
@ -4308,7 +4307,7 @@ SimdTypeToArrayElementType(SimdType type)
|
|||
bool
|
||||
IonBuilder::prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType,
|
||||
MInstruction** elements, MDefinition** index,
|
||||
Scalar::Type* arrayType, BoundsCheckKind boundsCheckKind)
|
||||
Scalar::Type* arrayType)
|
||||
{
|
||||
MDefinition* array = callInfo.getArg(0);
|
||||
*index = callInfo.getArg(1);
|
||||
|
@ -4334,20 +4333,20 @@ IonBuilder::prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType,
|
|||
}
|
||||
|
||||
MInstruction* length;
|
||||
addTypedArrayLengthAndData(array, SkipBoundsCheck, index, &length, elements, boundsCheckKind);
|
||||
addTypedArrayLengthAndData(array, SkipBoundsCheck, index, &length, elements);
|
||||
|
||||
// If the index+size addition overflows, then indexLoadEnd might be
|
||||
// in bounds while the actual index isn't, so we need two bounds checks
|
||||
// here.
|
||||
if (byteLoadSize > 1) {
|
||||
indexLoadEnd = addBoundsCheck(indexLoadEnd, length, BoundsCheckKind::IsLoad);
|
||||
indexLoadEnd = addBoundsCheck(indexLoadEnd, length);
|
||||
auto* sub = MSub::New(alloc(), indexLoadEnd, constant(Int32Value(byteLoadSize - 1)));
|
||||
sub->setInt32Specialization();
|
||||
current->add(sub);
|
||||
*index = sub;
|
||||
}
|
||||
|
||||
*index = addBoundsCheck(*index, length, boundsCheckKind);
|
||||
*index = addBoundsCheck(*index, length);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4364,11 +4363,8 @@ IonBuilder::inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type, u
|
|||
MDefinition* index = nullptr;
|
||||
MInstruction* elements = nullptr;
|
||||
Scalar::Type arrayType;
|
||||
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType,
|
||||
BoundsCheckKind::IsLoad))
|
||||
{
|
||||
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType))
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MLoadUnboxedScalar* load = MLoadUnboxedScalar::New(alloc(), elements, index, arrayType);
|
||||
load->setResultType(SimdTypeToMIRType(type));
|
||||
|
@ -4389,11 +4385,8 @@ IonBuilder::inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type,
|
|||
MDefinition* index = nullptr;
|
||||
MInstruction* elements = nullptr;
|
||||
Scalar::Type arrayType;
|
||||
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType,
|
||||
BoundsCheckKind::IsStore))
|
||||
{
|
||||
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType))
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* valueToWrite = unboxSimd(callInfo.getArg(2), type);
|
||||
MStoreUnboxedScalar* store = MStoreUnboxedScalar::New(alloc(), elements, index,
|
||||
|
|
|
@ -9705,7 +9705,8 @@ class MSpectreMaskIndex
|
|||
MSpectreMaskIndex(MDefinition* index, MDefinition* length)
|
||||
: MBinaryInstruction(classOpcode, index, length)
|
||||
{
|
||||
setGuard();
|
||||
// Note: this instruction does not need setGuard(): if there are no uses
|
||||
// it's fine for DCE to eliminate this instruction.
|
||||
setMovable();
|
||||
MOZ_ASSERT(index->type() == MIRType::Int32);
|
||||
MOZ_ASSERT(length->type() == MIRType::Int32);
|
||||
|
|
Загрузка…
Ссылка в новой задаче