From 79d8ceec1b523fec7e6842e327f3ea9578fee7b4 Mon Sep 17 00:00:00 2001 From: Iain Ireland Date: Fri, 28 Aug 2020 08:11:52 +0000 Subject: [PATCH] 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 --- js/src/jit/MIRBuilderShared.h | 15 +++++ js/src/jit/WarpBuilderShared.cpp | 1 + js/src/jit/WarpCacheIRTranspiler.cpp | 97 ++++++++++++++-------------- 3 files changed, 65 insertions(+), 48 deletions(-) diff --git a/js/src/jit/MIRBuilderShared.h b/js/src/jit/MIRBuilderShared.h index 6dc9c846554d..bd4ba76e7739 100644 --- a/js/src/jit/MIRBuilderShared.h +++ b/js/src/jit/MIRBuilderShared.h @@ -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 { diff --git a/js/src/jit/WarpBuilderShared.cpp b/js/src/jit/WarpBuilderShared.cpp index a8d5f7096b4e..9dcf3eac053c 100644 --- a/js/src/jit/WarpBuilderShared.cpp +++ b/js/src/jit/WarpBuilderShared.cpp @@ -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. diff --git a/js/src/jit/WarpCacheIRTranspiler.cpp b/js/src/jit/WarpCacheIRTranspiler.cpp index c6a3d656b604..6a24f27036b6 100644 --- a/js/src/jit/WarpCacheIRTranspiler.cpp +++ b/js/src/jit/WarpCacheIRTranspiler.cpp @@ -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(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; }