mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1659424 - Transpile AllocateAndStoreDynamicSlot. r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D87269
This commit is contained in:
parent
f0910370b4
commit
c3ccd2a7fa
@ -116,6 +116,7 @@ static inline const MDefinition* GetObject(const MDefinition* ins) {
|
||||
case MDefinition::Opcode::StoreDataViewElement:
|
||||
case MDefinition::Opcode::SetInitializedLength:
|
||||
case MDefinition::Opcode::AddAndStoreSlot:
|
||||
case MDefinition::Opcode::AllocateAndStoreSlot:
|
||||
case MDefinition::Opcode::ArrayLength:
|
||||
case MDefinition::Opcode::SetArrayLength:
|
||||
case MDefinition::Opcode::Slots:
|
||||
|
@ -4686,6 +4686,7 @@ AttachDecision SetPropIRGenerator::tryAttachAddSlotStub(
|
||||
// shape guard below) to ensure class is unchanged. This group guard may also
|
||||
// imply maybeInterpretedFunction() for the special-case of function
|
||||
// prototype property set.
|
||||
// TODO(Warp): Figure out if this can be removed without TI.
|
||||
writer.guardGroup(objId, oldGroup);
|
||||
|
||||
// If we are adding a property to an object for which the new script
|
||||
|
@ -841,7 +841,7 @@
|
||||
|
||||
- name: AllocateAndStoreDynamicSlot
|
||||
shared: false
|
||||
transpile: false
|
||||
transpile: true
|
||||
cost_estimate: 6
|
||||
args:
|
||||
obj: ObjId
|
||||
|
@ -11757,6 +11757,43 @@ void CodeGenerator::visitAddAndStoreSlot(LAddAndStoreSlot* ins) {
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::visitAllocateAndStoreSlot(LAllocateAndStoreSlot* ins) {
|
||||
const Register obj = ToRegister(ins->getOperand(0));
|
||||
const ValueOperand value = ToValue(ins, LAllocateAndStoreSlot::Value);
|
||||
const Register temp1 = ToRegister(ins->getTemp(0));
|
||||
const Register temp2 = ToRegister(ins->getTemp(1));
|
||||
|
||||
masm.push(obj);
|
||||
masm.pushValue(value);
|
||||
|
||||
masm.setupUnalignedABICall(temp1);
|
||||
masm.loadJSContext(temp1);
|
||||
masm.passABIArg(temp1);
|
||||
masm.passABIArg(obj);
|
||||
masm.move32(Imm32(ins->mir()->numNewSlots()), temp2);
|
||||
masm.passABIArg(temp2);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::growSlotsPure));
|
||||
masm.storeCallBoolResult(temp1);
|
||||
|
||||
masm.popValue(value);
|
||||
masm.pop(obj);
|
||||
|
||||
Label bail;
|
||||
masm.branchIfFalseBool(temp1, &bail);
|
||||
bailoutFrom(&bail, ins->snapshot());
|
||||
|
||||
masm.storeObjShape(ins->mir()->shape(), obj,
|
||||
[](MacroAssembler& masm, const Address& addr) {
|
||||
EmitPreBarrier(masm, addr, MIRType::Shape);
|
||||
});
|
||||
|
||||
// Perform the store. No pre-barrier required since this is a new
|
||||
// initialization.
|
||||
masm.loadPtr(Address(obj, NativeObject::offsetOfSlots()), temp1);
|
||||
Address slot(temp1, ins->mir()->slotOffset());
|
||||
masm.storeValue(value, slot);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitStoreFixedSlotV(LStoreFixedSlotV* ins) {
|
||||
const Register obj = ToRegister(ins->getOperand(0));
|
||||
size_t slot = ins->mir()->slot();
|
||||
|
@ -3922,6 +3922,16 @@ void LIRGenerator::visitAddAndStoreSlot(MAddAndStoreSlot* ins) {
|
||||
add(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitAllocateAndStoreSlot(MAllocateAndStoreSlot* ins) {
|
||||
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
||||
|
||||
auto* lir = new (alloc()) LAllocateAndStoreSlot(
|
||||
useRegisterAtStart(ins->object()), useBoxAtStart(ins->value()),
|
||||
tempFixed(CallTempReg0), tempFixed(CallTempReg1));
|
||||
assignSnapshot(lir, BailoutKind::DuringVMCall);
|
||||
add(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitStoreFixedSlot(MStoreFixedSlot* ins) {
|
||||
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
||||
|
||||
|
@ -10003,6 +10003,39 @@ class MAddAndStoreSlot
|
||||
}
|
||||
};
|
||||
|
||||
class MAllocateAndStoreSlot
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<SingleObjectPolicy, BoxPolicy<1>>::Data {
|
||||
private:
|
||||
CompilerShape shape_;
|
||||
uint32_t slotOffset_;
|
||||
uint32_t numNewSlots_;
|
||||
|
||||
MAllocateAndStoreSlot(MDefinition* obj, MDefinition* value,
|
||||
uint32_t slotOffset, Shape* shape, uint32_t numNewSlots)
|
||||
: MBinaryInstruction(classOpcode, obj, value),
|
||||
shape_(shape),
|
||||
slotOffset_(slotOffset),
|
||||
numNewSlots_(numNewSlots) {}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AllocateAndStoreSlot)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, object), (1, value))
|
||||
|
||||
Shape* shape() const { return shape_; }
|
||||
uint32_t slotOffset() const { return slotOffset_; }
|
||||
uint32_t numNewSlots() const { return numNewSlots_; }
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Store(AliasSet::ObjectFields | AliasSet::DynamicSlot);
|
||||
}
|
||||
bool possiblyCalls() const override { return true; }
|
||||
bool appendRoots(MRootList& roots) const override {
|
||||
return roots.append(shape_);
|
||||
}
|
||||
};
|
||||
|
||||
// Store to vp[slot] (slots that are not inline in an object).
|
||||
class MStoreDynamicSlot : public MBinaryInstruction,
|
||||
public NoFloatPolicy<1>::Data {
|
||||
|
@ -1386,6 +1386,29 @@ bool WarpCacheIRTranspiler::emitAddAndStoreDynamicSlot(
|
||||
offsetOffset, rhsId, newShapeOffset);
|
||||
}
|
||||
|
||||
bool WarpCacheIRTranspiler::emitAllocateAndStoreDynamicSlot(
|
||||
ObjOperandId objId, uint32_t offsetOffset, ValOperandId rhsId,
|
||||
bool changeGroup, uint32_t newGroupOffset, uint32_t newShapeOffset,
|
||||
uint32_t numNewSlotsOffset) {
|
||||
MOZ_ASSERT(!changeGroup);
|
||||
|
||||
int32_t offset = int32StubField(offsetOffset);
|
||||
Shape* shape = shapeStubField(newShapeOffset);
|
||||
uint32_t numNewSlots = uint32StubField(numNewSlotsOffset);
|
||||
|
||||
MDefinition* obj = getOperand(objId);
|
||||
MDefinition* rhs = getOperand(rhsId);
|
||||
|
||||
auto* barrier = MPostWriteBarrier::New(alloc(), obj, rhs);
|
||||
add(barrier);
|
||||
|
||||
auto* allocateAndStore =
|
||||
MAllocateAndStoreSlot::New(alloc(), obj, rhs, offset, shape, numNewSlots);
|
||||
addEffectful(allocateAndStore);
|
||||
|
||||
return resumeAfter(allocateAndStore);
|
||||
}
|
||||
|
||||
bool WarpCacheIRTranspiler::emitStoreDenseElement(ObjOperandId objId,
|
||||
Int32OperandId indexId,
|
||||
ValOperandId rhsId) {
|
||||
|
@ -4999,6 +4999,27 @@ class LAddAndStoreSlot : public LInstructionHelper<0, 1 + BOX_PIECES, 1> {
|
||||
const MAddAndStoreSlot* mir() const { return mir_->toAddAndStoreSlot(); }
|
||||
};
|
||||
|
||||
class LAllocateAndStoreSlot
|
||||
: public LCallInstructionHelper<0, 1 + BOX_PIECES, 2> {
|
||||
public:
|
||||
LIR_HEADER(AllocateAndStoreSlot)
|
||||
|
||||
LAllocateAndStoreSlot(const LAllocation& obj, const LBoxAllocation& value,
|
||||
const LDefinition& temp1, const LDefinition& temp2)
|
||||
: LCallInstructionHelper(classOpcode) {
|
||||
setOperand(0, obj);
|
||||
setBoxOperand(Value, value);
|
||||
setTemp(0, temp1);
|
||||
setTemp(1, temp2);
|
||||
}
|
||||
|
||||
static const size_t Value = 1;
|
||||
|
||||
const MAllocateAndStoreSlot* mir() const {
|
||||
return mir_->toAllocateAndStoreSlot();
|
||||
}
|
||||
};
|
||||
|
||||
// Store a boxed value to an object's fixed slot.
|
||||
class LStoreFixedSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0> {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user