Bug 1445235 part 6 - Use spectreBoundsCheck32 for more stores in JIT code. r=nbp

This commit is contained in:
Jan de Mooij 2018-03-28 16:09:04 +02:00
Родитель f9a2b1497d
Коммит b82103f0d5
6 изменённых файлов: 176 добавлений и 84 удалений

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

@ -1380,9 +1380,11 @@ BaselineCacheIRCompiler::emitStoreDenseElement()
// Load obj->elements in scratch.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
// Bounds check.
// Bounds check. Unfortunately we don't have more registers available on
// x86, so use InvalidReg and emit slightly slower code on x86.
Register spectreTemp = InvalidReg;
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, index, failure->label());
masm.spectreBoundsCheck32(index, initLength, spectreTemp, failure->label());
// Hole check.
BaseObjectElementIndex element(scratch, index);
@ -1471,18 +1473,30 @@ BaselineCacheIRCompiler::emitStoreDenseElementHole()
ObjectElements::FROZEN),
failure->label());
// We don't have enough registers on x86 so use InvalidReg. This will emit
// slightly less efficient code on x86.
Register spectreTemp = InvalidReg;
if (handleAdd) {
// Fail if index > initLength.
masm.branch32(Assembler::Below, initLength, index, failure->label());
// Bounds check.
Label capacityOk, outOfBounds;
masm.spectreBoundsCheck32(index, initLength, spectreTemp, &outOfBounds);
masm.jump(&capacityOk);
// If we're out-of-bounds, only handle the index == initLength case.
masm.bind(&outOfBounds);
masm.branch32(Assembler::NotEqual, initLength, index, failure->label());
// If index < capacity, we can add a dense element inline. If not we
// need to allocate more elements.
Label capacityOk;
Label allocElement;
Address capacity(scratch, ObjectElements::offsetOfCapacity());
masm.branch32(Assembler::Above, capacity, index, &capacityOk);
masm.spectreBoundsCheck32(index, capacity, spectreTemp, &allocElement);
masm.jump(&capacityOk);
// Check for non-writable array length. We only have to do this if
// index >= capacity.
masm.bind(&allocElement);
masm.branchTest32(Assembler::NonZero, elementsFlags,
Imm32(ObjectElements::NONWRITABLE_ARRAY_LENGTH),
failure->label());
@ -1510,7 +1524,7 @@ BaselineCacheIRCompiler::emitStoreDenseElementHole()
// the type update code doesn't read uninitialized memory.
} else {
// Fail if index >= initLength.
masm.branch32(Assembler::BelowOrEqual, initLength, index, failure->label());
masm.spectreBoundsCheck32(index, initLength, spectreTemp, failure->label());
}
// Check if we have to convert a double element.
@ -1595,10 +1609,9 @@ BaselineCacheIRCompiler::emitArrayPush()
// Load obj->elements in scratch.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
masm.load32(Address(scratch, ObjectElements::offsetOfLength()), scratchLength);
BaseObjectElementIndex element(scratch, scratchLength);
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
Address elementsInitLength(scratch, ObjectElements::offsetOfInitializedLength());
Address elementsLength(scratch, ObjectElements::offsetOfLength());
Address elementsFlags(scratch, ObjectElements::offsetOfFlags());
// Check for copy-on-write or frozen elements.
@ -1608,16 +1621,19 @@ BaselineCacheIRCompiler::emitArrayPush()
failure->label());
// Fail if length != initLength.
masm.branch32(Assembler::NotEqual, initLength, scratchLength, failure->label());
masm.load32(elementsInitLength, scratchLength);
masm.branch32(Assembler::NotEqual, elementsLength, scratchLength, failure->label());
// If scratchLength < capacity, we can add a dense element inline. If not we
// need to allocate more elements.
Label capacityOk;
Label capacityOk, allocElement;
Address capacity(scratch, ObjectElements::offsetOfCapacity());
masm.branch32(Assembler::Above, capacity, scratchLength, &capacityOk);
masm.spectreBoundsCheck32(scratchLength, capacity, InvalidReg, &allocElement);
masm.jump(&capacityOk);
// Check for non-writable array length. We only have to do this if
// index >= capacity.
masm.bind(&allocElement);
masm.branchTest32(Assembler::NonZero, elementsFlags,
Imm32(ObjectElements::NONWRITABLE_ARRAY_LENGTH),
failure->label());
@ -1672,12 +1688,12 @@ BaselineCacheIRCompiler::emitArrayPush()
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
// Increment initLength and length.
Address length(scratch, ObjectElements::offsetOfLength());
masm.add32(Imm32(1), initLength);
masm.load32(length, scratchLength);
masm.add32(Imm32(1), length);
masm.add32(Imm32(1), elementsInitLength);
masm.load32(elementsLength, scratchLength);
masm.add32(Imm32(1), elementsLength);
// Store the value.
BaseObjectElementIndex element(scratch, scratchLength);
masm.storeValue(val, element);
emitPostBarrierElement(obj, val, scratch, scratchLength);
@ -1708,7 +1724,11 @@ BaselineCacheIRCompiler::emitStoreTypedElement()
// Bounds check.
Label done;
LoadTypedThingLength(masm, layout, obj, scratch1);
masm.branch32(Assembler::BelowOrEqual, scratch1, index, handleOOB ? &done : failure->label());
// Unfortunately we don't have more registers available on x86, so use
// InvalidReg and emit slightly slower code on x86.
Register spectreTemp = InvalidReg;
masm.spectreBoundsCheck32(index, scratch1, spectreTemp, handleOOB ? &done : failure->label());
// Load the elements vector.
LoadTypedThingData(masm, layout, obj, scratch1);

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

@ -9227,9 +9227,10 @@ CodeGenerator::emitStoreElementHoleT(T* lir)
Register elements = ToRegister(lir->elements());
Register index = ToRegister(lir->index());
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
Address initLength(elements, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, index, ool->entry());
masm.spectreBoundsCheck32(index, initLength, spectreTemp, ool->entry());
if (lir->mir()->needsBarrier())
emitPreBarrier(elements, lir->index(), 0);
@ -9260,9 +9261,10 @@ CodeGenerator::emitStoreElementHoleV(T* lir)
Register elements = ToRegister(lir->elements());
Register index = ToRegister(lir->index());
const ValueOperand value = ToValue(lir, T::Value);
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
Address initLength(elements, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, index, ool->entry());
masm.spectreBoundsCheck32(index, initLength, spectreTemp, ool->entry());
if (lir->mir()->needsBarrier())
emitPreBarrier(elements, lir->index(), 0);
@ -9360,6 +9362,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
const LAllocation* index;
MIRType valueType;
ConstantOrRegister value;
Register spectreTemp;
if (ins->isStoreElementHoleV()) {
LStoreElementHoleV* store = ins->toStoreElementHoleV();
@ -9368,6 +9371,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
index = store->index();
valueType = store->mir()->value()->type();
value = TypedOrValueRegister(ToValue(store, LStoreElementHoleV::Value));
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
} else if (ins->isFallibleStoreElementV()) {
LFallibleStoreElementV* store = ins->toFallibleStoreElementV();
object = ToRegister(store->object());
@ -9375,6 +9379,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
index = store->index();
valueType = store->mir()->value()->type();
value = TypedOrValueRegister(ToValue(store, LFallibleStoreElementV::Value));
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
} else if (ins->isStoreElementHoleT()) {
LStoreElementHoleT* store = ins->toStoreElementHoleT();
object = ToRegister(store->object());
@ -9385,6 +9390,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
else
value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
} else { // ins->isFallibleStoreElementT()
LFallibleStoreElementT* store = ins->toFallibleStoreElementT();
object = ToRegister(store->object());
@ -9395,6 +9401,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
else
value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
}
Register indexReg = ToRegister(index);
@ -9402,6 +9409,8 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
// If index == initializedLength, try to bump the initialized length inline.
// If index > initializedLength, call a stub. Note that this relies on the
// condition flags sticking from the incoming branch.
// Also note: this branch does not need Spectre mitigations, doing that for
// the capacity check below is sufficient.
Label callStub;
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
// Had to reimplement for MIPS because there are no flags.
@ -9412,8 +9421,8 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
#endif
// Check array capacity.
masm.branch32(Assembler::BelowOrEqual, Address(elements, ObjectElements::offsetOfCapacity()),
indexReg, &callStub);
masm.spectreBoundsCheck32(indexReg, Address(elements, ObjectElements::offsetOfCapacity()),
spectreTemp, &callStub);
// Update initialized length. The capacity guard above ensures this won't overflow,
// due to MAX_DENSE_ELEMENTS_COUNT.
@ -9558,12 +9567,13 @@ CodeGenerator::emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, R
// VM call if a write barrier is necessary.
masm.branchTestNeedsIncrementalBarrier(Assembler::NonZero, ool->entry());
// Load elements and length, and VM call if length != initializedLength.
// Load elements and initializedLength, and VM call if
// length != initializedLength.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), lengthTemp);
masm.load32(Address(elementsTemp, ObjectElements::offsetOfInitializedLength()), lengthTemp);
Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::NotEqual, initLength, lengthTemp, ool->entry());
Address lengthAddr(elementsTemp, ObjectElements::offsetOfLength());
masm.branch32(Assembler::NotEqual, lengthAddr, lengthTemp, ool->entry());
// Test for length != 0. On zero length either take a VM call or generate
// an undefined value, depending on whether the call is known to produce
@ -9655,7 +9665,8 @@ static const VMFunction ArrayPushDenseInfo =
void
CodeGenerator::emitArrayPush(LInstruction* lir, Register obj,
const ConstantOrRegister& value, Register elementsTemp, Register length)
const ConstantOrRegister& value, Register elementsTemp, Register length,
Register spectreTemp)
{
OutOfLineCode* ool = oolCallVM(ArrayPushDenseInfo, lir, ArgList(obj, value), StoreRegisterTo(length));
@ -9669,7 +9680,7 @@ CodeGenerator::emitArrayPush(LInstruction* lir, Register obj,
// Guard length < capacity.
Address capacity(elementsTemp, ObjectElements::offsetOfCapacity());
masm.branch32(Assembler::BelowOrEqual, capacity, length, ool->entry());
masm.spectreBoundsCheck32(length, capacity, spectreTemp, ool->entry());
// Do the store.
masm.storeConstantOrRegister(value, BaseIndex(elementsTemp, length, TimesEight));
@ -9690,7 +9701,8 @@ CodeGenerator::visitArrayPushV(LArrayPushV* lir)
Register elementsTemp = ToRegister(lir->temp());
Register length = ToRegister(lir->output());
ConstantOrRegister value = TypedOrValueRegister(ToValue(lir, LArrayPushV::Value));
emitArrayPush(lir, obj, value, elementsTemp, length);
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
emitArrayPush(lir, obj, value, elementsTemp, length, spectreTemp);
}
void
@ -9704,7 +9716,8 @@ CodeGenerator::visitArrayPushT(LArrayPushT* lir)
value = ConstantOrRegister(lir->value()->toConstant()->toJSValue());
else
value = TypedOrValueRegister(lir->mir()->value()->type(), ToAnyRegister(lir->value()));
emitArrayPush(lir, obj, value, elementsTemp, length);
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
emitArrayPush(lir, obj, value, elementsTemp, length, spectreTemp);
}
typedef JSObject* (*ArraySliceDenseFn)(JSContext*, HandleObject, int32_t, int32_t, HandleObject);

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

@ -163,7 +163,8 @@ class CodeGenerator final : public CodeGeneratorSpecific
void emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, Register obj,
Register elementsTemp, Register lengthTemp, TypedOrValueRegister out);
void emitArrayPush(LInstruction* lir, Register obj,
const ConstantOrRegister& value, Register elementsTemp, Register length);
const ConstantOrRegister& value, Register elementsTemp, Register length,
Register spectreTemp);
void emitRest(LInstruction* lir, Register array, Register numActuals,
Register temp0, Register temp1, unsigned numFormals,

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

@ -1901,7 +1901,8 @@ IonCacheIRCompiler::emitStoreDenseElement()
Register index = allocator.useRegister(masm, reader.int32OperandId());
ConstantOrRegister val = allocator.useConstantOrRegister(masm, reader.valOperandId());
AutoScratchRegister scratch(allocator, masm);
AutoScratchRegister scratch1(allocator, masm);
AutoScratchRegister scratch2(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
@ -1910,20 +1911,20 @@ IonCacheIRCompiler::emitStoreDenseElement()
EmitCheckPropertyTypes(masm, typeCheckInfo_, obj, val, *liveRegs_, failure->label());
// Load obj->elements in scratch.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch1);
// Bounds check.
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, index, failure->label());
Address initLength(scratch1, ObjectElements::offsetOfInitializedLength());
masm.spectreBoundsCheck32(index, initLength, scratch2, failure->label());
// Hole check.
BaseObjectElementIndex element(scratch, index);
BaseObjectElementIndex element(scratch1, index);
masm.branchTestMagic(Assembler::Equal, element, failure->label());
EmitPreBarrier(masm, element, MIRType::Value);
EmitStoreDenseElement(masm, val, scratch, element);
EmitStoreDenseElement(masm, val, scratch1, element);
if (needsPostBarrier())
emitPostBarrierElement(obj, val, scratch, index);
emitPostBarrierElement(obj, val, scratch1, index);
return true;
}
@ -1939,7 +1940,8 @@ IonCacheIRCompiler::emitStoreDenseElementHole()
// track this.
reader.readBool();
AutoScratchRegister scratch(allocator, masm);
AutoScratchRegister scratch1(allocator, masm);
AutoScratchRegister scratch2(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
@ -1947,45 +1949,51 @@ IonCacheIRCompiler::emitStoreDenseElementHole()
EmitCheckPropertyTypes(masm, typeCheckInfo_, obj, val, *liveRegs_, failure->label());
// Load obj->elements in scratch.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
// Load obj->elements in scratch1.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch1);
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
BaseObjectElementIndex element(scratch, index);
Address initLength(scratch1, ObjectElements::offsetOfInitializedLength());
BaseObjectElementIndex element(scratch1, index);
Label inBounds, doStore;
masm.branch32(Assembler::Above, initLength, index, &inBounds);
Label inBounds, outOfBounds;
Register spectreTemp = scratch2;
masm.spectreBoundsCheck32(index, initLength, spectreTemp, &outOfBounds);
masm.jump(&inBounds);
masm.bind(&outOfBounds);
masm.branch32(Assembler::NotEqual, initLength, index, failure->label());
// If index < capacity, we can add a dense element inline. If not we
// need to allocate more elements.
Label capacityOk;
Address capacity(scratch, ObjectElements::offsetOfCapacity());
masm.branch32(Assembler::Above, capacity, index, &capacityOk);
Label capacityOk, allocElement;
Address capacity(scratch1, ObjectElements::offsetOfCapacity());
masm.spectreBoundsCheck32(index, capacity, spectreTemp, &allocElement);
masm.jump(&capacityOk);
// Check for non-writable array length. We only have to do this if
// index >= capacity.
Address elementsFlags(scratch, ObjectElements::offsetOfFlags());
masm.bind(&allocElement);
Address elementsFlags(scratch1, ObjectElements::offsetOfFlags());
masm.branchTest32(Assembler::NonZero, elementsFlags,
Imm32(ObjectElements::NONWRITABLE_ARRAY_LENGTH),
failure->label());
LiveRegisterSet save(GeneralRegisterSet::Volatile(), liveVolatileFloatRegs());
save.takeUnchecked(scratch);
save.takeUnchecked(scratch1);
masm.PushRegsInMask(save);
masm.setupUnalignedABICall(scratch);
masm.loadJSContext(scratch);
masm.passABIArg(scratch);
masm.setupUnalignedABICall(scratch1);
masm.loadJSContext(scratch1);
masm.passABIArg(scratch1);
masm.passABIArg(obj);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::addDenseElementDontReportOOM));
masm.mov(ReturnReg, scratch);
masm.mov(ReturnReg, scratch1);
masm.PopRegsInMask(save);
masm.branchIfFalseBool(scratch, failure->label());
masm.branchIfFalseBool(scratch1, failure->label());
// Load the reallocated elements pointer.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch1);
masm.bind(&capacityOk);
@ -1994,12 +2002,13 @@ IonCacheIRCompiler::emitStoreDenseElementHole()
// If length is now <= index, increment length too.
Label skipIncrementLength;
Address length(scratch, ObjectElements::offsetOfLength());
Address length(scratch1, ObjectElements::offsetOfLength());
masm.branch32(Assembler::Above, length, index, &skipIncrementLength);
masm.add32(Imm32(1), length);
masm.bind(&skipIncrementLength);
// Skip EmitPreBarrier as the memory is uninitialized.
Label doStore;
masm.jump(&doStore);
masm.bind(&inBounds);
@ -2007,9 +2016,9 @@ IonCacheIRCompiler::emitStoreDenseElementHole()
EmitPreBarrier(masm, element, MIRType::Value);
masm.bind(&doStore);
EmitStoreDenseElement(masm, val, scratch, element);
EmitStoreDenseElement(masm, val, scratch1, element);
if (needsPostBarrier())
emitPostBarrierElement(obj, val, scratch, index);
emitPostBarrierElement(obj, val, scratch1, index);
return true;
}
@ -2032,10 +2041,7 @@ IonCacheIRCompiler::emitStoreTypedElement()
bool handleOOB = reader.readBool();
AutoScratchRegister scratch1(allocator, masm);
Maybe<AutoScratchRegister> scratch2;
if (arrayType != Scalar::Float32 && arrayType != Scalar::Float64)
scratch2.emplace(allocator, masm);
AutoScratchRegister scratch2(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
@ -2044,7 +2050,7 @@ IonCacheIRCompiler::emitStoreTypedElement()
// Bounds check.
Label done;
LoadTypedThingLength(masm, layout, obj, scratch1);
masm.branch32(Assembler::BelowOrEqual, scratch1, index, handleOOB ? &done : failure->label());
masm.spectreBoundsCheck32(index, scratch1, scratch2, handleOOB ? &done : failure->label());
// Load the elements vector.
LoadTypedThingData(masm, layout, obj, scratch1);
@ -2066,7 +2072,7 @@ IonCacheIRCompiler::emitStoreTypedElement()
return false;
masm.storeToTypedFloatArray(arrayType, maybeTempDouble, dest);
} else {
Register valueToStore = scratch2.ref();
Register valueToStore = scratch2;
if (arrayType == Scalar::Uint8Clamped) {
if (!masm.clampConstantOrRegisterToUint8(cx_, val, maybeTempDouble, valueToStore,
failure->label()))

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

@ -3419,6 +3419,18 @@ LIRGenerator::visitStoreElement(MStoreElement* ins)
}
}
static bool
BoundsCheckNeedsSpectreTemp()
{
// On x86, spectreBoundsCheck32 can emit better code if it has a scratch
// register and index masking is enabled.
#ifdef JS_CODEGEN_X86
return JitOptions.spectreIndexMasking;
#else
return false;
#endif
}
void
LIRGenerator::visitStoreElementHole(MStoreElementHole* ins)
{
@ -3429,16 +3441,19 @@ LIRGenerator::visitStoreElementHole(MStoreElementHole* ins)
const LUse elements = useRegister(ins->elements());
const LAllocation index = useRegister(ins->index());
LDefinition spectreTemp = BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
LInstruction* lir;
switch (ins->value()->type()) {
case MIRType::Value:
lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()));
lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()),
spectreTemp);
break;
default:
{
const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
lir = new(alloc()) LStoreElementHoleT(object, elements, index, value);
lir = new(alloc()) LStoreElementHoleT(object, elements, index, value, spectreTemp);
break;
}
}
@ -3457,14 +3472,18 @@ LIRGenerator::visitFallibleStoreElement(MFallibleStoreElement* ins)
const LUse elements = useRegister(ins->elements());
const LAllocation index = useRegister(ins->index());
LDefinition spectreTemp = BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
LInstruction* lir;
switch (ins->value()->type()) {
case MIRType::Value:
lir = new(alloc()) LFallibleStoreElementV(object, elements, index, useBox(ins->value()));
lir = new(alloc()) LFallibleStoreElementV(object, elements, index, useBox(ins->value()),
spectreTemp);
break;
default:
const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
lir = new(alloc()) LFallibleStoreElementT(object, elements, index, value);
lir = new(alloc()) LFallibleStoreElementT(object, elements, index, value,
spectreTemp);
break;
}
@ -3563,10 +3582,13 @@ LIRGenerator::visitArrayPush(MArrayPush* ins)
LUse object = useRegister(ins->object());
LDefinition spectreTemp = BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
switch (ins->value()->type()) {
case MIRType::Value:
{
LArrayPushV* lir = new(alloc()) LArrayPushV(object, useBox(ins->value()), temp());
LArrayPushV* lir = new(alloc()) LArrayPushV(object, useBox(ins->value()), temp(),
spectreTemp);
define(lir, ins);
assignSafepoint(lir, ins);
break;
@ -3575,7 +3597,7 @@ LIRGenerator::visitArrayPush(MArrayPush* ins)
default:
{
const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
LArrayPushT* lir = new(alloc()) LArrayPushT(object, value, temp());
LArrayPushT* lir = new(alloc()) LArrayPushT(object, value, temp(), spectreTemp);
define(lir, ins);
assignSafepoint(lir, ins);
break;
@ -3798,7 +3820,7 @@ LIRGenerator::visitStoreTypedArrayElementHole(MStoreTypedArrayElementHole* ins)
else
value = useRegisterOrNonDoubleConstant(ins->value());
LDefinition spectreTemp = JitOptions.spectreIndexMasking ? temp() : LDefinition::BogusTemp();
LDefinition spectreTemp = BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
auto* lir =
new(alloc()) LStoreTypedArrayElementHole(elements, length, index, value, spectreTemp);
add(lir, ins);

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

@ -6440,19 +6440,21 @@ class LStoreElementT : public LInstructionHelper<0, 3, 0>
};
// Like LStoreElementV, but supports indexes >= initialized length.
class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
{
public:
LIR_HEADER(StoreElementHoleV)
LStoreElementHoleV(const LAllocation& object, const LAllocation& elements,
const LAllocation& index, const LBoxAllocation& value)
const LAllocation& index, const LBoxAllocation& value,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setBoxOperand(Value, value);
setTemp(0, spectreTemp);
}
static const size_t Value = 3;
@ -6469,22 +6471,27 @@ class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
const LAllocation* index() {
return getOperand(2);
}
const LDefinition* spectreTemp() {
return getTemp(0);
}
};
// Like LStoreElementT, but supports indexes >= initialized length.
class LStoreElementHoleT : public LInstructionHelper<0, 4, 0>
class LStoreElementHoleT : public LInstructionHelper<0, 4, 1>
{
public:
LIR_HEADER(StoreElementHoleT)
LStoreElementHoleT(const LAllocation& object, const LAllocation& elements,
const LAllocation& index, const LAllocation& value)
const LAllocation& index, const LAllocation& value,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setOperand(3, value);
setTemp(0, spectreTemp);
}
const MStoreElementHole* mir() const {
@ -6502,22 +6509,27 @@ class LStoreElementHoleT : public LInstructionHelper<0, 4, 0>
const LAllocation* value() {
return getOperand(3);
}
const LDefinition* spectreTemp() {
return getTemp(0);
}
};
// Like LStoreElementV, but can just ignore assignment (for eg. frozen objects)
class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
{
public:
LIR_HEADER(FallibleStoreElementV)
LFallibleStoreElementV(const LAllocation& object, const LAllocation& elements,
const LAllocation& index, const LBoxAllocation& value)
const LAllocation& index, const LBoxAllocation& value,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setBoxOperand(Value, value);
setTemp(0, spectreTemp);
}
static const size_t Value = 3;
@ -6534,22 +6546,27 @@ class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
const LAllocation* index() {
return getOperand(2);
}
const LDefinition* spectreTemp() {
return getTemp(0);
}
};
// Like LStoreElementT, but can just ignore assignment (for eg. frozen objects)
class LFallibleStoreElementT : public LInstructionHelper<0, 4, 0>
class LFallibleStoreElementT : public LInstructionHelper<0, 4, 1>
{
public:
LIR_HEADER(FallibleStoreElementT)
LFallibleStoreElementT(const LAllocation& object, const LAllocation& elements,
const LAllocation& index, const LAllocation& value)
const LAllocation& index, const LAllocation& value,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setOperand(3, value);
setTemp(0, spectreTemp);
}
const MFallibleStoreElement* mir() const {
@ -6567,6 +6584,9 @@ class LFallibleStoreElementT : public LInstructionHelper<0, 4, 0>
const LAllocation* value() {
return getOperand(3);
}
const LDefinition* spectreTemp() {
return getTemp(0);
}
};
class LStoreUnboxedPointer : public LInstructionHelper<0, 3, 0>
@ -6681,17 +6701,19 @@ class LArrayPopShiftT : public LInstructionHelper<1, 1, 2>
}
};
class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 2>
{
public:
LIR_HEADER(ArrayPushV)
LArrayPushV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp)
LArrayPushV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setBoxOperand(Value, value);
setTemp(0, temp);
setTemp(1, spectreTemp);
}
static const size_t Value = 1;
@ -6705,19 +6727,24 @@ class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
const LDefinition* temp() {
return getTemp(0);
}
const LDefinition* spectreTemp() {
return getTemp(1);
}
};
class LArrayPushT : public LInstructionHelper<1, 2, 1>
class LArrayPushT : public LInstructionHelper<1, 2, 2>
{
public:
LIR_HEADER(ArrayPushT)
LArrayPushT(const LAllocation& object, const LAllocation& value, const LDefinition& temp)
LArrayPushT(const LAllocation& object, const LAllocation& value, const LDefinition& temp,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, value);
setTemp(0, temp);
setTemp(1, spectreTemp);
}
const MArrayPush* mir() const {
@ -6732,6 +6759,9 @@ class LArrayPushT : public LInstructionHelper<1, 2, 1>
const LDefinition* temp() {
return getTemp(0);
}
const LDefinition* spectreTemp() {
return getTemp(1);
}
};
class LArraySlice : public LCallInstructionHelper<1, 3, 2>