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;
uint16_t id_;
OperandId() : id_(InvalidId) {}
explicit OperandId(uint16_t id) : id_(id) {}
public:
OperandId() : id_(InvalidId) {}
uint16_t id() const { return id_; }
bool valid() const { return id_ != InvalidId; }
};
@ -406,7 +406,8 @@ enum class ArgumentKind : uint8_t {
Arg0,
Arg1,
Arg2,
Arg3
Arg3,
NumKinds
};
// 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_;
// 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
// Used to assert that there is only one effectful instruction
// per stub. And that this instruction has a resume point.
@ -3430,6 +3443,46 @@ bool WarpCacheIRTranspiler::emitLoadWrapperTarget(ObjOperandId objId,
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,
uint32_t slotIndex) {
// Reverse of GetIndexOfArgument.
@ -3442,6 +3495,7 @@ bool WarpCacheIRTranspiler::emitLoadArgumentSlot(ValOperandId resultId,
// NewTarget (optional)
if (callInfo_->constructing()) {
if (slotIndex == 0) {
setArgumentId(ArgumentKind::NewTarget, resultId);
return defineOperand(resultId, callInfo_->getNewTarget());
}
@ -3451,11 +3505,15 @@ bool WarpCacheIRTranspiler::emitLoadArgumentSlot(ValOperandId resultId,
// Args..
if (slotIndex < callInfo_->argc()) {
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));
}
// ThisValue
if (slotIndex == callInfo_->argc()) {
setArgumentId(ArgumentKind::This, resultId);
return defineOperand(resultId, callInfo_->thisArg());
}
@ -3544,6 +3602,10 @@ bool WarpCacheIRTranspiler::updateCallInfo(MDefinition* callee,
// the resulting call instruction depends on these guards.
callInfo_->setCallee(callee);
// The transpilation may also add guards to other arguments.
// We replace those arguments in the CallInfo here.
updateArgumentsFromOperands();
switch (flags.getArgFormat()) {
case CallFlags::Standard:
MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Standard);
@ -3552,7 +3614,7 @@ bool WarpCacheIRTranspiler::updateCallInfo(MDefinition* callee,
MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Array);
break;
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.
MOZ_ASSERT(!callInfo_->constructing());
MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Standard);