Bug 1675084: Ensure call node depends on guards r=jandem

Differential Revision: https://phabricator.services.mozilla.com/D95771
This commit is contained in:
Iain Ireland 2020-11-09 22:47:19 +00:00
Родитель d13debb6cd
Коммит b5623086d5
2 изменённых файлов: 66 добавлений и 3 удалений

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

@ -86,10 +86,10 @@ class OperandId {
static const uint16_t InvalidId = UINT16_MAX; static const uint16_t InvalidId = UINT16_MAX;
uint16_t id_; uint16_t id_;
OperandId() : id_(InvalidId) {}
explicit OperandId(uint16_t id) : id_(id) {} explicit OperandId(uint16_t id) : id_(id) {}
public: public:
OperandId() : id_(InvalidId) {}
uint16_t id() const { return id_; } uint16_t id() const { return id_; }
bool valid() const { return id_ != InvalidId; } bool valid() const { return id_ != InvalidId; }
}; };
@ -406,7 +406,8 @@ enum class ArgumentKind : uint8_t {
Arg0, Arg0,
Arg1, Arg1,
Arg2, Arg2,
Arg3 Arg3,
NumKinds
}; };
// This function calculates the index of an argument based on the call flags. // This function calculates the index of an argument based on the call flags.

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

@ -47,6 +47,19 @@ class MOZ_RAII WarpCacheIRTranspiler : public WarpBuilderShared {
CallInfo* callInfo_; CallInfo* callInfo_;
// Array mapping call arguments to OperandId.
using ArgumentKindArray =
mozilla::EnumeratedArray<ArgumentKind, ArgumentKind::NumKinds, OperandId>;
ArgumentKindArray argumentOperandIds_;
void setArgumentId(ArgumentKind kind, OperandId id) {
MOZ_ASSERT(kind != ArgumentKind::Callee);
MOZ_ASSERT(!argumentOperandIds_[kind].valid());
argumentOperandIds_[kind] = id;
}
void updateArgumentsFromOperands();
#ifdef DEBUG #ifdef DEBUG
// Used to assert that there is only one effectful instruction // Used to assert that there is only one effectful instruction
// per stub. And that this instruction has a resume point. // per stub. And that this instruction has a resume point.
@ -3430,6 +3443,46 @@ bool WarpCacheIRTranspiler::emitLoadWrapperTarget(ObjOperandId objId,
return defineOperand(resultId, ins); return defineOperand(resultId, ins);
} }
// When we transpile a call, we may generate guards for some
// arguments. To make sure the call instruction depends on those
// guards, when the transpiler creates an operand for an argument, we
// register the OperandId of that argument in argumentIds_. (See
// emitLoadArgumentSlot.) Before generating the call, we update the
// CallInfo to use the appropriate value from operands_.
// Note: The callee is an explicit argument to the call op, and is
// tracked separately.
void WarpCacheIRTranspiler::updateArgumentsFromOperands() {
for (uint32_t i = 0; i < uint32_t(ArgumentKind::NumKinds); i++) {
ArgumentKind kind = ArgumentKind(i);
OperandId id = argumentOperandIds_[kind];
if (id.valid()) {
switch (kind) {
case ArgumentKind::This:
callInfo_->setThis(getOperand(id));
break;
case ArgumentKind::NewTarget:
callInfo_->setNewTarget(getOperand(id));
break;
case ArgumentKind::Arg0:
callInfo_->setArg(0, getOperand(id));
break;
case ArgumentKind::Arg1:
callInfo_->setArg(1, getOperand(id));
break;
case ArgumentKind::Arg2:
callInfo_->setArg(2, getOperand(id));
break;
case ArgumentKind::Arg3:
callInfo_->setArg(3, getOperand(id));
break;
case ArgumentKind::Callee:
case ArgumentKind::NumKinds:
MOZ_CRASH("Unexpected argument kind");
}
}
}
}
bool WarpCacheIRTranspiler::emitLoadArgumentSlot(ValOperandId resultId, bool WarpCacheIRTranspiler::emitLoadArgumentSlot(ValOperandId resultId,
uint32_t slotIndex) { uint32_t slotIndex) {
// Reverse of GetIndexOfArgument. // Reverse of GetIndexOfArgument.
@ -3442,6 +3495,7 @@ bool WarpCacheIRTranspiler::emitLoadArgumentSlot(ValOperandId resultId,
// NewTarget (optional) // NewTarget (optional)
if (callInfo_->constructing()) { if (callInfo_->constructing()) {
if (slotIndex == 0) { if (slotIndex == 0) {
setArgumentId(ArgumentKind::NewTarget, resultId);
return defineOperand(resultId, callInfo_->getNewTarget()); return defineOperand(resultId, callInfo_->getNewTarget());
} }
@ -3451,11 +3505,15 @@ bool WarpCacheIRTranspiler::emitLoadArgumentSlot(ValOperandId resultId,
// Args.. // Args..
if (slotIndex < callInfo_->argc()) { if (slotIndex < callInfo_->argc()) {
uint32_t arg = callInfo_->argc() - 1 - slotIndex; uint32_t arg = callInfo_->argc() - 1 - slotIndex;
ArgumentKind kind = ArgumentKind(uint32_t(ArgumentKind::Arg0) + arg);
MOZ_ASSERT(kind < ArgumentKind::NumKinds);
setArgumentId(kind, resultId);
return defineOperand(resultId, callInfo_->getArg(arg)); return defineOperand(resultId, callInfo_->getArg(arg));
} }
// ThisValue // ThisValue
if (slotIndex == callInfo_->argc()) { if (slotIndex == callInfo_->argc()) {
setArgumentId(ArgumentKind::This, resultId);
return defineOperand(resultId, callInfo_->thisArg()); return defineOperand(resultId, callInfo_->thisArg());
} }
@ -3544,6 +3602,10 @@ bool WarpCacheIRTranspiler::updateCallInfo(MDefinition* callee,
// the resulting call instruction depends on these guards. // the resulting call instruction depends on these guards.
callInfo_->setCallee(callee); callInfo_->setCallee(callee);
// The transpilation may also add guards to other arguments.
// We replace those arguments in the CallInfo here.
updateArgumentsFromOperands();
switch (flags.getArgFormat()) { switch (flags.getArgFormat()) {
case CallFlags::Standard: case CallFlags::Standard:
MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Standard); MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Standard);
@ -3552,7 +3614,7 @@ bool WarpCacheIRTranspiler::updateCallInfo(MDefinition* callee,
MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Array); MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Array);
break; break;
case CallFlags::FunCall: case CallFlags::FunCall:
// Note: setCallee above already changed the callee to the target // Note: We already changed the callee to the target
// function instead of the |call| function. // function instead of the |call| function.
MOZ_ASSERT(!callInfo_->constructing()); MOZ_ASSERT(!callInfo_->constructing());
MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Standard); MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Standard);