@@ -7925,10 +7925,14 @@ Js::ArgSlot EmitNewObjectOfConstants(
79257925 return actualArgCount;
79267926}
79277927
7928- void EmitMethodFld (bool isRoot, bool isScoped, Js::RegSlot location, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true )
7928+ void EmitMethodFld (bool isRoot, bool isScoped, bool isNullPropagating, Js::RegSlot location, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true )
79297929{
79307930 Js::OpCode opcode;
7931- if (!isRoot)
7931+ if (isNullPropagating)
7932+ {
7933+ opcode = (!isScoped && isRoot) ? Js::OpCode::LdRootFld : Js::OpCode::LdFld;
7934+ }
7935+ else if (!isRoot)
79327936 {
79337937 if (callObjLocation == funcInfo->frameObjRegister )
79347938 {
@@ -7968,15 +7972,15 @@ void EmitMethodFld(bool isRoot, bool isScoped, Js::RegSlot location, Js::RegSlot
79687972 }
79697973}
79707974
7971- void EmitMethodFld (ParseNode *pnode, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true )
7975+ void EmitMethodFld (ParseNodeCall *pnodeCall, ParseNode *pnode, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true )
79727976{
79737977 // Load a call target of the form x.y(). (Call target may be a plain knopName if we're getting it from
79747978 // the global object, etc.)
79757979 bool isRoot = pnode->nop == knopName && (pnode->AsParseNodeName ()->sym == nullptr || pnode->AsParseNodeName ()->sym ->GetIsGlobal ());
79767980 bool isScoped = (byteCodeGenerator->GetFlags () & fscrEval) != 0 ||
79777981 (isRoot && callObjLocation != ByteCodeGenerator::RootObjectRegister);
79787982
7979- EmitMethodFld (isRoot, isScoped, pnode->location , callObjLocation, propertyId, byteCodeGenerator, funcInfo, registerCacheIdForCall);
7983+ EmitMethodFld (isRoot, isScoped, pnodeCall-> isNullPropagating , pnode->location , callObjLocation, propertyId, byteCodeGenerator, funcInfo, registerCacheIdForCall);
79807984}
79817985
79827986// lhs.apply(this, arguments);
@@ -8003,7 +8007,7 @@ void EmitApplyCall(ParseNodeCall* pnodeCall, ByteCodeGenerator* byteCodeGenerato
80038007 // call for apply, we won't remove the entry for "apply" cacheId from
80048008 // ByteCodeWriter::callRegToLdFldCacheIndexMap, which is contrary to our assumption that we would
80058009 // have removed an entry from a map upon seeing its corresponding call.
8006- EmitMethodFld (applyNode, funcNode->location , propertyId, byteCodeGenerator, funcInfo, false /* registerCacheIdForCall*/ );
8010+ EmitMethodFld (pnodeCall, applyNode, funcNode->location , propertyId, byteCodeGenerator, funcInfo, false /* registerCacheIdForCall*/ );
80078011
80088012 Symbol *argSym = funcInfo->GetArgumentsSymbol ();
80098013 Assert (argSym && argSym->IsArguments ());
@@ -8106,6 +8110,7 @@ void EmitCallTargetNoEvalComponents(
81068110}
81078111
81088112void EmitCallTarget (
8113+ ParseNodeCall *pnodeCall,
81098114 ParseNode *pnodeTarget,
81108115 BOOL fSideEffectArgs ,
81118116 Js::RegSlot *thisLocation,
@@ -8130,7 +8135,7 @@ void EmitCallTarget(
81308135 {
81318136 case knopOptChain: {
81328137 EmitOptionalChainWrapper (pnodeTarget->AsParseNodeUni (), byteCodeGenerator, funcInfo, [&](ParseNodePtr innerNode) {
8133- EmitCallTarget (innerNode, fSideEffectArgs , thisLocation, releaseThisLocation, callObjLocation, byteCodeGenerator, funcInfo, callApplyCallSiteId);
8138+ EmitCallTarget (pnodeCall, innerNode, fSideEffectArgs , thisLocation, releaseThisLocation, callObjLocation, byteCodeGenerator, funcInfo, callApplyCallSiteId);
81348139 });
81358140 break ;
81368141 }
@@ -8179,7 +8184,7 @@ void EmitCallTarget(
81798184 {
81808185 *thisLocation = pnodeBinTarget->pnode1 ->location ;
81818186 EmitNullPropagation (pnodeBinTarget->pnode1 ->location , byteCodeGenerator, funcInfo, pnodeBinTarget->isNullPropagating );
8182- EmitMethodFld (pnodeBinTarget, protoLocation, propertyId, byteCodeGenerator, funcInfo);
8187+ EmitMethodFld (pnodeCall, pnodeBinTarget, protoLocation, propertyId, byteCodeGenerator, funcInfo);
81838188 }
81848189
81858190 break ;
@@ -8247,7 +8252,7 @@ void EmitCallTarget(
82478252 {
82488253 // Load the call target as a property of the instance.
82498254 Js::PropertyId propertyId = pnodeNameTarget->PropertyIdFromNameNode ();
8250- EmitMethodFld (pnodeNameTarget, *callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8255+ EmitMethodFld (pnodeCall, pnodeNameTarget, *callObjLocation, propertyId, byteCodeGenerator, funcInfo);
82518256 break ;
82528257 }
82538258 }
@@ -8403,7 +8408,7 @@ void EmitCallInstrNoEvalComponents(
84038408 Assert (pnodeTarget->AsParseNodeBin ()->pnode2 ->nop == knopName);
84048409 Js::PropertyId propertyId = pnodeTarget->AsParseNodeBin ()->pnode2 ->AsParseNodeName ()->PropertyIdFromNameNode ();
84058410
8406- EmitMethodFld (pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8411+ EmitMethodFld (pnodeCall, pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
84078412 EmitCallI (pnodeCall, /* fEvaluateComponents*/ FALSE , fIsEval , fHasNewTarget , actualArgCount, byteCodeGenerator, funcInfo, callSiteId, spreadIndices);
84088413 }
84098414 break ;
@@ -8427,7 +8432,7 @@ void EmitCallInstrNoEvalComponents(
84278432 funcInfo->ReleaseTmpRegister (callObjLocation);
84288433
84298434 Js::PropertyId propertyId = pnodeTarget->AsParseNodeName ()->PropertyIdFromNameNode ();
8430- EmitMethodFld (pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8435+ EmitMethodFld (pnodeCall, pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
84318436 EmitCallI (pnodeCall, /* fEvaluateComponents*/ FALSE , fIsEval , fHasNewTarget , actualArgCount, byteCodeGenerator, funcInfo, callSiteId, spreadIndices);
84328437 break ;
84338438 }
@@ -8652,7 +8657,7 @@ void EmitCall(
86528657 }
86538658 else
86548659 {
8655- EmitCallTarget (pnodeTarget, fSideEffectArgs , &thisLocation, &releaseThisLocation, &callObjLocation, byteCodeGenerator, funcInfo, &callApplyCallSiteId);
8660+ EmitCallTarget (pnodeCall, pnodeTarget, fSideEffectArgs , &thisLocation, &releaseThisLocation, &callObjLocation, byteCodeGenerator, funcInfo, &callApplyCallSiteId);
86568661 }
86578662 }
86588663
@@ -8704,7 +8709,7 @@ void EmitInvoke(
87048709 ByteCodeGenerator* byteCodeGenerator,
87058710 FuncInfo* funcInfo)
87068711{
8707- EmitMethodFld (false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8712+ EmitMethodFld (false , false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
87088713
87098714 funcInfo->StartRecordingOutArgs (1 );
87108715
@@ -8724,7 +8729,7 @@ void EmitInvoke(
87248729 FuncInfo* funcInfo,
87258730 Js::RegSlot arg1Location)
87268731{
8727- EmitMethodFld (false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8732+ EmitMethodFld (false , false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
87288733
87298734 funcInfo->StartRecordingOutArgs (2 );
87308735
0 commit comments