зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
9ae99bc021
Коммит
79d8ceec1b
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче