Bug 1687441 part 11 - Add MAdjustDataViewLength. r=anba

The alternative is to add support for MIRType::IntPtr to MSub and MMinMax which
seemed more complicated.

This also matches the IC code in EmitDataViewBoundsCheck. A later patch will
change codegen to branchSubPtr.

Depends on D102727

Differential Revision: https://phabricator.services.mozilla.com/D102728
This commit is contained in:
Jan de Mooij 2021-01-26 09:03:04 +00:00
parent 43faccb34b
commit e72d91e082
5 changed files with 79 additions and 23 deletions

View File

@ -1235,6 +1235,24 @@ void CodeGenerator::visitFloat32ToIntegerInt32(LFloat32ToIntegerInt32* lir) {
masm.bind(ool->rejoin());
}
void CodeGenerator::visitAdjustDataViewLength(LAdjustDataViewLength* lir) {
Register output = ToRegister(lir->output());
MOZ_ASSERT(ToRegister(lir->input()) == output);
uint32_t byteSize = lir->mir()->byteSize();
#ifdef DEBUG
Label ok;
masm.branchTest32(Assembler::NotSigned, output, output, &ok);
masm.assumeUnreachable("Unexpected negative value in LAdjustDataViewLength");
masm.bind(&ok);
#endif
Label bail;
masm.branchSub32(Assembler::Signed, Imm32(byteSize - 1), output, &bail);
bailoutFrom(&bail, lir->snapshot());
}
void CodeGenerator::emitOOLTestObject(Register objreg,
Label* ifEmulatesUndefined,
Label* ifDoesntEmulateUndefined,

View File

@ -2222,6 +2222,15 @@ void LIRGenerator::visitTruncateToInt32(MTruncateToInt32* truncate) {
}
}
void LIRGenerator::visitAdjustDataViewLength(MAdjustDataViewLength* ins) {
MDefinition* input = ins->input();
MOZ_ASSERT(input->type() == MIRType::Int32);
auto* lir = new (alloc()) LAdjustDataViewLength(useRegisterAtStart(input));
assignSnapshot(lir, ins->bailoutKind());
defineReuseInput(lir, ins, 0);
}
void LIRGenerator::visitToBigInt(MToBigInt* ins) {
MDefinition* opd = ins->input();

View File

@ -3246,10 +3246,7 @@ class MReturnFromCtor : public MBinaryInstruction,
class MToFPInstruction : public MUnaryInstruction, public ToDoublePolicy::Data {
public:
// Types of values which can be converted.
enum ConversionKind {
NonStringPrimitives,
NumbersOnly
};
enum ConversionKind { NonStringPrimitives, NumbersOnly };
private:
ConversionKind conversion_;
@ -3624,6 +3621,39 @@ class MWasmAnyRefFromJSObject : public MUnaryInstruction,
AliasSet getAliasSet() const override { return AliasSet::None(); }
};
// Subtracts (byteSize - 1) from the input value. Bails out if the result is
// negative. This is used to implement bounds checks for DataView accesses.
class MAdjustDataViewLength : public MUnaryInstruction,
public NoTypePolicy::Data {
const uint32_t byteSize_;
MAdjustDataViewLength(MDefinition* input, uint32_t byteSize)
: MUnaryInstruction(classOpcode, input), byteSize_(byteSize) {
MOZ_ASSERT(input->type() == MIRType::Int32);
MOZ_ASSERT(byteSize > 1);
setResultType(MIRType::Int32);
setMovable();
setGuard();
}
public:
INSTRUCTION_HEADER(AdjustDataViewLength)
TRIVIAL_NEW_WRAPPERS
uint32_t byteSize() const { return byteSize_; }
bool congruentTo(const MDefinition* ins) const override {
if (!ins->isAdjustDataViewLength()) {
return false;
}
if (ins->toAdjustDataViewLength()->byteSize() != byteSize()) {
return false;
}
return congruentIfOperandsEqual(ins);
}
AliasSet getAliasSet() const override { return AliasSet::None(); }
};
class MInt64ToFloatingPoint : public MUnaryInstruction,
public NoTypePolicy::Data {
bool isUnsigned_;

View File

@ -2137,25 +2137,10 @@ void WarpCacheIRTranspiler::addDataViewData(MDefinition* obj, Scalar::Type type,
// Adjust the length to account for accesses near the end of the dataview.
if (size_t byteSize = Scalar::byteSize(type); byteSize > 1) {
// To ensure |0 <= offset && offset + byteSize <= length|, we can either
// emit |BoundsCheck(offset, length)| followed by
// |BoundsCheck(offset + (byteSize - 1), length)|, or alternatively emit
// |BoundsCheck(offset, Max(length - (byteSize - 1), 0))|. The latter should
// result in faster code when LICM moves the length adjustment and also
// ensures Spectre index masking occurs after all bounds checks.
auto* byteSizeMinusOne = MConstant::New(alloc(), Int32Value(byteSize - 1));
add(byteSizeMinusOne);
length = MSub::New(alloc(), length, byteSizeMinusOne, MIRType::Int32);
length->toSub()->setTruncateKind(TruncateKind::Truncate);
add(length);
// |length| mustn't be negative for MBoundsCheck.
auto* zero = MConstant::New(alloc(), Int32Value(0));
add(zero);
length = MMinMax::New(alloc(), length, zero, MIRType::Int32, true);
// To ensure |0 <= offset && offset + byteSize <= length|, first adjust the
// length by subtracting |byteSize - 1| (bailing out if that becomes
// negative).
length = MAdjustDataViewLength::New(alloc(), length, byteSize);
add(length);
}

View File

@ -5601,6 +5601,20 @@ class LRest : public LCallInstructionHelper<1, 1, 3> {
MRest* mir() const { return mir_->toRest(); }
};
class LAdjustDataViewLength : public LInstructionHelper<1, 1, 0> {
public:
LIR_HEADER(AdjustDataViewLength)
explicit LAdjustDataViewLength(const LAllocation& input)
: LInstructionHelper(classOpcode) {
setOperand(0, input);
}
const MAdjustDataViewLength* mir() const {
return mir_->toAdjustDataViewLength();
}
};
// Convert a Boolean to an Int64, following ToBigInt.
class LBooleanToInt64 : public LInstructionHelper<INT64_PIECES, 1, 0> {
public: