Bug 1661352: Store arg format in CallInfo r=jandem

This makes transpiling nicer, and should also make inlining much easier.

Depends on D88511

Differential Revision: https://phabricator.services.mozilla.com/D88512
This commit is contained in:
Iain Ireland 2020-08-28 08:11:52 +00:00
Родитель 9ae99bc021
Коммит 79d8ceec1b
3 изменённых файлов: 65 добавлений и 48 удалений

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

@ -122,6 +122,18 @@ class MOZ_STACK_CLASS CallInfo {
bool setter_ = false;
bool apply_;
public:
// For some argument formats (normal calls, FunCall, FunApplyArgs in an
// inlined function) we can shuffle around definitions in the CallInfo
// and use a normal MCall. For others, we need to use a specialized call.
enum class ArgFormat {
Standard,
FunApplyArgs,
};
private:
ArgFormat argFormat_ = ArgFormat::Standard;
public:
CallInfo(TempAllocator& alloc, jsbytecode* pc, bool constructing,
bool ignoresReturnValue)
@ -324,6 +336,9 @@ class MOZ_STACK_CLASS CallInfo {
auto setFlag = [](MDefinition* def) { def->setImplicitlyUsedUnchecked(); };
forEachCallOperand(setFlag);
}
ArgFormat argFormat() const { return argFormat_; }
void setArgFormat(ArgFormat argFormat) { argFormat_ = argFormat; }
};
class AutoAccumulateReturns {

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

@ -50,6 +50,7 @@ void WarpBuilderShared::pushConstant(const Value& v) {
MCall* WarpBuilderShared::makeCall(CallInfo& callInfo, bool needsThisCheck,
WrappedFunction* target) {
MOZ_ASSERT(callInfo.argFormat() == CallInfo::ArgFormat::Standard);
MOZ_ASSERT_IF(needsThisCheck, !target);
// TODO: Investigate DOM calls.

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

@ -171,20 +171,13 @@ class MOZ_RAII WarpCacheIRTranspiler : public WarpBuilderShared {
// (scripted function or native function with a JitEntry).
enum class CallKind { Native, Scripted };
// For some argument formats (normal calls, FunCall, FunApplyArgs in an
// inlined function) we can shuffle around definitions in the CallInfo
// and use a normal MCall. For others, we need to use a specialized call.
// TODO: Support spread calls.
enum class ArgumentLocation { OOM, Standard, FunApplyArgs };
MOZ_MUST_USE ArgumentLocation updateCallInfo(MDefinition* callee,
CallFlags flags);
MOZ_MUST_USE bool updateCallInfo(MDefinition* callee, CallFlags flags);
MOZ_MUST_USE bool emitCallFunction(ObjOperandId calleeId,
Int32OperandId argcId, CallFlags flags,
CallKind kind);
MOZ_MUST_USE bool emitFunApplyArgs(MDefinition* callee, CallFlags flags,
CallKind kind);
MOZ_MUST_USE bool emitFunApplyArgs(WrappedFunction* wrappedTarget,
CallFlags flags);
WrappedFunction* maybeWrappedFunction(MDefinition* callee, CallKind kind,
uint16_t nargs, FunctionFlags flags);
@ -3079,10 +3072,10 @@ WrappedFunction* WarpCacheIRTranspiler::maybeCallTarget(MDefinition* callee,
guard->flags());
}
// If it is possible to use MCall for this call, update callInfo_ to
// use the correct arguments.
WarpCacheIRTranspiler::ArgumentLocation WarpCacheIRTranspiler::updateCallInfo(
MDefinition* callee, CallFlags flags) {
// If it is possible to use MCall for this call, update callInfo_ to use
// the correct arguments. Otherwise, update the ArgFormat of callInfo_.
bool WarpCacheIRTranspiler::updateCallInfo(MDefinition* callee,
CallFlags flags) {
// The transpilation will add various guards to the callee.
// We replace the callee referenced by the CallInfo, so that
// the resulting call instruction depends on these guards.
@ -3090,11 +3083,13 @@ WarpCacheIRTranspiler::ArgumentLocation WarpCacheIRTranspiler::updateCallInfo(
switch (flags.getArgFormat()) {
case CallFlags::Standard:
return ArgumentLocation::Standard;
MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Standard);
break;
case CallFlags::FunCall:
// Note: setCallee above already changed the callee to the target
// function instead of the |call| function.
MOZ_ASSERT(!callInfo_->constructing());
MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Standard);
if (callInfo_->argc() == 0) {
// Special case for fun.call() with no arguments.
@ -3107,26 +3102,30 @@ WarpCacheIRTranspiler::ArgumentLocation WarpCacheIRTranspiler::updateCallInfo(
// Shift down all other arguments by removing the first.
callInfo_->removeArg(0);
}
return ArgumentLocation::Standard;
break;
case CallFlags::FunApplyArgs:
MOZ_ASSERT(!callInfo_->constructing());
MOZ_ASSERT(callInfo_->argFormat() == CallInfo::ArgFormat::Standard);
// If we are building an inlined function, we know the arguments
// being used.
MOZ_ASSERT(!callInfo_->constructing());
if (const CallInfo* outerCallInfo = builder_->inlineCallInfo()) {
MDefinition* argFunc = callInfo_->thisArg();
MDefinition* argThis = callInfo_->getArg(0);
if (!callInfo_->replaceArgs(outerCallInfo->argv())) {
return ArgumentLocation::OOM;
return false;
}
callInfo_->setCallee(argFunc);
callInfo_->setThis(argThis);
return ArgumentLocation::Standard;
} else {
callInfo_->setArgFormat(CallInfo::ArgFormat::FunApplyArgs);
}
return ArgumentLocation::FunApplyArgs;
break;
default:
MOZ_CRASH("Unsupported arg format");
}
return true;
}
bool WarpCacheIRTranspiler::emitCallFunction(ObjOperandId calleeId,
@ -3139,13 +3138,8 @@ bool WarpCacheIRTranspiler::emitCallFunction(ObjOperandId calleeId,
static_cast<int32_t>(callInfo_->argc()));
#endif
switch (updateCallInfo(callee, flags)) {
case ArgumentLocation::Standard:
break;
case ArgumentLocation::FunApplyArgs:
return emitFunApplyArgs(callee, flags, kind);
case ArgumentLocation::OOM:
return false;
if (!updateCallInfo(callee, flags)) {
return false;
}
WrappedFunction* wrappedTarget = maybeCallTarget(callee, kind);
@ -3188,28 +3182,34 @@ bool WarpCacheIRTranspiler::emitCallFunction(ObjOperandId calleeId,
}
}
MCall* call = makeCall(*callInfo_, needsThisCheck, wrappedTarget);
if (!call) {
return false;
switch (callInfo_->argFormat()) {
case CallInfo::ArgFormat::Standard: {
MCall* call = makeCall(*callInfo_, needsThisCheck, wrappedTarget);
if (!call) {
return false;
}
if (flags.isSameRealm()) {
call->setNotCrossRealm();
}
addEffectful(call);
pushResult(call);
return resumeAfter(call);
}
case CallInfo::ArgFormat::FunApplyArgs: {
return emitFunApplyArgs(wrappedTarget, flags);
}
}
if (flags.isSameRealm()) {
call->setNotCrossRealm();
}
addEffectful(call);
pushResult(call);
return resumeAfter(call);
MOZ_CRASH("unreachable");
}
bool WarpCacheIRTranspiler::emitFunApplyArgs(MDefinition* callee,
CallFlags flags, CallKind kind) {
bool WarpCacheIRTranspiler::emitFunApplyArgs(WrappedFunction* wrappedTarget,
CallFlags flags) {
MOZ_ASSERT(!callInfo_->constructing());
MOZ_ASSERT(!builder_->inlineCallInfo());
WrappedFunction* wrappedTarget = maybeCallTarget(callee, kind);
MDefinition* argFunc = callInfo_->thisArg();
MDefinition* argThis = callInfo_->getArg(0);
@ -3265,13 +3265,14 @@ bool WarpCacheIRTranspiler::emitCallInlinedFunction(ObjOperandId calleeId,
// inlined function itself will be generated in
// WarpBuilder::buildInlinedCall.
MDefinition* callee = getOperand(calleeId);
switch (updateCallInfo(callee, flags)) {
case ArgumentLocation::Standard:
if (!updateCallInfo(callee, flags)) {
return false;
}
switch (callInfo_->argFormat()) {
case CallInfo::ArgFormat::Standard:
break;
case ArgumentLocation::OOM:
return false;
default:
MOZ_CRASH("Unsupported argument location");
MOZ_CRASH("Unsupported arg format");
}
return true;
}