Bug 1647250 - Fix MArrayLength to check for non-int32 array lengths in Warp. r=evilpie

Differential Revision: https://phabricator.services.mozilla.com/D81670
This commit is contained in:
Jan de Mooij 2020-06-30 10:45:51 +00:00
Родитель 8ad6c00a5a
Коммит ac180368d0
6 изменённых файлов: 39 добавлений и 6 удалений

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

@ -0,0 +1,10 @@
function f(arr, len) {
for (var i = 0; i < 2000; i++) {
assertEq(arr.length, len);
}
}
var arr = [0];
f(arr, 1);
arr.length = 0xffff_ffff;
f(arr, 0xffff_ffff);

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

@ -2001,6 +2001,7 @@ bool jit::FinishBailoutToBaseline(BaselineBailoutInfo* bailoutInfoArg) {
case Bailout_Debugger:
case Bailout_SpecificAtomGuard:
case Bailout_SpecificSymbolGuard:
case Bailout_NonInt32ArrayLength:
// Do nothing.
break;

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

@ -7640,8 +7640,19 @@ void CodeGenerator::visitArrowNewTarget(LArrowNewTarget* lir) {
}
void CodeGenerator::visitArrayLength(LArrayLength* lir) {
Address length(ToRegister(lir->elements()), ObjectElements::offsetOfLength());
masm.load32(length, ToRegister(lir->output()));
Register elements = ToRegister(lir->elements());
Register output = ToRegister(lir->output());
Address length(elements, ObjectElements::offsetOfLength());
masm.load32(length, output);
// IonBuilder relies on TI knowing the length fits in int32, but Warp needs to
// check this dynamically.
if (JitOptions.warpBuilder) {
Label bail;
masm.branchTest32(Assembler::Signed, output, output, &bail);
bailoutFrom(&bail, lir->snapshot());
}
}
static void SetLengthFromIndex(MacroAssembler& masm, const LAllocation* index,

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

@ -144,6 +144,9 @@ enum BailoutKind {
// We hit this code for the first time.
Bailout_FirstExecution,
// Array length did not fit in int32.
Bailout_NonInt32ArrayLength,
// END Normal bailouts
// Bailouts caused by invalid assumptions based on Baseline code.
@ -246,6 +249,8 @@ inline const char* BailoutKindString(BailoutKind kind) {
return "Bailout_Debugger";
case Bailout_FirstExecution:
return "Bailout_FirstExecution";
case Bailout_NonInt32ArrayLength:
return "Bailout_NonInt32ArrayLength";
// Bailouts caused by invalid assumptions.
case Bailout_OverflowInvalidate:

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

@ -2996,7 +2996,11 @@ void LIRGenerator::visitPostWriteElementBarrier(MPostWriteElementBarrier* ins) {
void LIRGenerator::visitArrayLength(MArrayLength* ins) {
MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
define(new (alloc()) LArrayLength(useRegisterAtStart(ins->elements())), ins);
auto* lir = new (alloc()) LArrayLength(useRegisterAtStart(ins->elements()));
if (JitOptions.warpBuilder) {
assignSnapshot(lir, Bailout_NonInt32ArrayLength);
}
define(lir, ins);
}
void LIRGenerator::visitSetArrayLength(MSetArrayLength* ins) {

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

@ -1769,10 +1769,12 @@ void MLoadDataViewElement::computeRange(TempAllocator& alloc) {
}
void MArrayLength::computeRange(TempAllocator& alloc) {
// Array lengths can go up to UINT32_MAX, but we only create MArrayLength
// Array lengths can go up to UINT32_MAX. IonBuilder only creates MArrayLength
// nodes when the value is known to be int32 (see the
// OBJECT_FLAG_LENGTH_OVERFLOW flag).
setRange(Range::NewUInt32Range(alloc, 0, INT32_MAX));
// OBJECT_FLAG_LENGTH_OVERFLOW flag). WarpBuilder does a dynamic check and we
// have to return the range pre-bailouts, so use UINT32_MAX for Warp.
uint32_t max = JitOptions.warpBuilder ? UINT32_MAX : INT32_MAX;
setRange(Range::NewUInt32Range(alloc, 0, max));
}
void MInitializedLength::computeRange(TempAllocator& alloc) {