@@ -81,7 +81,7 @@ static void EmitOptionalChainWrapper(ParseNodeUni *pnodeOptChain, ByteCodeGenera
8181 byteCodeGenerator->Writer ()->Br (doneLabel);
8282 }
8383
84- byteCodeGenerator->Writer ()->MarkLabel (skipLabel);
84+ byteCodeGenerator->Writer ()->MarkLabel (skipLabel);
8585
8686 if (pnodeOptChain->isUsed )
8787 {
@@ -7928,10 +7928,14 @@ Js::ArgSlot EmitNewObjectOfConstants(
79287928 return actualArgCount;
79297929}
79307930
7931- void EmitMethodFld (bool isRoot, bool isScoped, Js::RegSlot location, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true )
7931+ void EmitMethodFld (bool isRoot, bool isScoped, bool isNullPropagating, Js::RegSlot location, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true )
79327932{
79337933 Js::OpCode opcode;
7934- if (!isRoot)
7934+ if (isNullPropagating)
7935+ {
7936+ opcode = (!isScoped && isRoot) ? Js::OpCode::LdRootFld : Js::OpCode::LdFld;
7937+ }
7938+ else if (!isRoot)
79357939 {
79367940 if (callObjLocation == funcInfo->frameObjRegister )
79377941 {
@@ -7971,15 +7975,15 @@ void EmitMethodFld(bool isRoot, bool isScoped, Js::RegSlot location, Js::RegSlot
79717975 }
79727976}
79737977
7974- void EmitMethodFld (ParseNode *pnode, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true )
7978+ void EmitMethodFld (ParseNodeCall *pnodeCall, ParseNode *pnode, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true )
79757979{
79767980 // Load a call target of the form x.y(). (Call target may be a plain knopName if we're getting it from
79777981 // the global object, etc.)
79787982 bool isRoot = pnode->nop == knopName && (pnode->AsParseNodeName ()->sym == nullptr || pnode->AsParseNodeName ()->sym ->GetIsGlobal ());
79797983 bool isScoped = (byteCodeGenerator->GetFlags () & fscrEval) != 0 ||
79807984 (isRoot && callObjLocation != ByteCodeGenerator::RootObjectRegister);
79817985
7982- EmitMethodFld (isRoot, isScoped, pnode->location , callObjLocation, propertyId, byteCodeGenerator, funcInfo, registerCacheIdForCall);
7986+ EmitMethodFld (isRoot, isScoped, pnodeCall-> isNullPropagating , pnode->location , callObjLocation, propertyId, byteCodeGenerator, funcInfo, registerCacheIdForCall);
79837987}
79847988
79857989// lhs.apply(this, arguments);
@@ -8006,7 +8010,7 @@ void EmitApplyCall(ParseNodeCall* pnodeCall, ByteCodeGenerator* byteCodeGenerato
80068010 // call for apply, we won't remove the entry for "apply" cacheId from
80078011 // ByteCodeWriter::callRegToLdFldCacheIndexMap, which is contrary to our assumption that we would
80088012 // have removed an entry from a map upon seeing its corresponding call.
8009- EmitMethodFld (applyNode, funcNode->location , propertyId, byteCodeGenerator, funcInfo, false /* registerCacheIdForCall*/ );
8013+ EmitMethodFld (pnodeCall, applyNode, funcNode->location , propertyId, byteCodeGenerator, funcInfo, false /* registerCacheIdForCall*/ );
80108014
80118015 Symbol *argSym = funcInfo->GetArgumentsSymbol ();
80128016 Assert (argSym && argSym->IsArguments ());
@@ -8109,6 +8113,7 @@ void EmitCallTargetNoEvalComponents(
81098113}
81108114
81118115void EmitCallTarget (
8116+ ParseNodeCall *pnodeCall,
81128117 ParseNode *pnodeTarget,
81138118 BOOL fSideEffectArgs ,
81148119 Js::RegSlot *thisLocation,
@@ -8133,7 +8138,7 @@ void EmitCallTarget(
81338138 {
81348139 case knopOptChain: {
81358140 EmitOptionalChainWrapper (pnodeTarget->AsParseNodeUni (), byteCodeGenerator, funcInfo, [&](ParseNodePtr innerNode) {
8136- EmitCallTarget (innerNode, fSideEffectArgs , thisLocation, releaseThisLocation, callObjLocation, byteCodeGenerator, funcInfo, callApplyCallSiteId);
8141+ EmitCallTarget (pnodeCall, innerNode, fSideEffectArgs , thisLocation, releaseThisLocation, callObjLocation, byteCodeGenerator, funcInfo, callApplyCallSiteId);
81378142 });
81388143 break ;
81398144 }
@@ -8182,7 +8187,7 @@ void EmitCallTarget(
81828187 {
81838188 *thisLocation = pnodeBinTarget->pnode1 ->location ;
81848189 EmitNullPropagation (pnodeBinTarget->pnode1 ->location , byteCodeGenerator, funcInfo, pnodeBinTarget->isNullPropagating );
8185- EmitMethodFld (pnodeBinTarget, protoLocation, propertyId, byteCodeGenerator, funcInfo);
8190+ EmitMethodFld (pnodeCall, pnodeBinTarget, protoLocation, propertyId, byteCodeGenerator, funcInfo);
81868191 }
81878192
81888193 break ;
@@ -8250,7 +8255,7 @@ void EmitCallTarget(
82508255 {
82518256 // Load the call target as a property of the instance.
82528257 Js::PropertyId propertyId = pnodeNameTarget->PropertyIdFromNameNode ();
8253- EmitMethodFld (pnodeNameTarget, *callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8258+ EmitMethodFld (pnodeCall, pnodeNameTarget, *callObjLocation, propertyId, byteCodeGenerator, funcInfo);
82548259 break ;
82558260 }
82568261 }
@@ -8406,7 +8411,7 @@ void EmitCallInstrNoEvalComponents(
84068411 Assert (pnodeTarget->AsParseNodeBin ()->pnode2 ->nop == knopName);
84078412 Js::PropertyId propertyId = pnodeTarget->AsParseNodeBin ()->pnode2 ->AsParseNodeName ()->PropertyIdFromNameNode ();
84088413
8409- EmitMethodFld (pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8414+ EmitMethodFld (pnodeCall, pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
84108415 EmitCallI (pnodeCall, /* fEvaluateComponents*/ FALSE , fIsEval , fHasNewTarget , actualArgCount, byteCodeGenerator, funcInfo, callSiteId, spreadIndices);
84118416 }
84128417 break ;
@@ -8430,7 +8435,7 @@ void EmitCallInstrNoEvalComponents(
84308435 funcInfo->ReleaseTmpRegister (callObjLocation);
84318436
84328437 Js::PropertyId propertyId = pnodeTarget->AsParseNodeName ()->PropertyIdFromNameNode ();
8433- EmitMethodFld (pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8438+ EmitMethodFld (pnodeCall, pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
84348439 EmitCallI (pnodeCall, /* fEvaluateComponents*/ FALSE , fIsEval , fHasNewTarget , actualArgCount, byteCodeGenerator, funcInfo, callSiteId, spreadIndices);
84358440 break ;
84368441 }
@@ -8655,7 +8660,7 @@ void EmitCall(
86558660 }
86568661 else
86578662 {
8658- EmitCallTarget (pnodeTarget, fSideEffectArgs , &thisLocation, &releaseThisLocation, &callObjLocation, byteCodeGenerator, funcInfo, &callApplyCallSiteId);
8663+ EmitCallTarget (pnodeCall, pnodeTarget, fSideEffectArgs , &thisLocation, &releaseThisLocation, &callObjLocation, byteCodeGenerator, funcInfo, &callApplyCallSiteId);
86598664 }
86608665 }
86618666
@@ -8707,7 +8712,7 @@ void EmitInvoke(
87078712 ByteCodeGenerator* byteCodeGenerator,
87088713 FuncInfo* funcInfo)
87098714{
8710- EmitMethodFld (false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8715+ EmitMethodFld (false , false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
87118716
87128717 funcInfo->StartRecordingOutArgs (1 );
87138718
@@ -8727,7 +8732,7 @@ void EmitInvoke(
87278732 FuncInfo* funcInfo,
87288733 Js::RegSlot arg1Location)
87298734{
8730- EmitMethodFld (false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8735+ EmitMethodFld (false , false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
87318736
87328737 funcInfo->StartRecordingOutArgs (2 );
87338738
0 commit comments