@@ -7926,10 +7926,14 @@ Js::ArgSlot EmitNewObjectOfConstants(
7926
7926
return actualArgCount;
7927
7927
}
7928
7928
7929
- void EmitMethodFld(bool isRoot, bool isScoped, Js::RegSlot location, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true)
7929
+ void EmitMethodFld(bool isRoot, bool isScoped, bool isNullPropagating, Js::RegSlot location, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true)
7930
7930
{
7931
7931
Js::OpCode opcode;
7932
- if (!isRoot)
7932
+ if (isNullPropagating)
7933
+ {
7934
+ opcode = Js::OpCode::LdFld;
7935
+ }
7936
+ else if (!isRoot)
7933
7937
{
7934
7938
if (callObjLocation == funcInfo->frameObjRegister)
7935
7939
{
@@ -7969,15 +7973,15 @@ void EmitMethodFld(bool isRoot, bool isScoped, Js::RegSlot location, Js::RegSlot
7969
7973
}
7970
7974
}
7971
7975
7972
- void EmitMethodFld(ParseNode *pnode, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true)
7976
+ void EmitMethodFld(ParseNodeCall *pnodeCall, ParseNode *pnode, Js::RegSlot callObjLocation, Js::PropertyId propertyId, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo, bool registerCacheIdForCall = true)
7973
7977
{
7974
7978
// Load a call target of the form x.y(). (Call target may be a plain knopName if we're getting it from
7975
7979
// the global object, etc.)
7976
7980
bool isRoot = pnode->nop == knopName && (pnode->AsParseNodeName()->sym == nullptr || pnode->AsParseNodeName()->sym->GetIsGlobal());
7977
7981
bool isScoped = (byteCodeGenerator->GetFlags() & fscrEval) != 0 ||
7978
7982
(isRoot && callObjLocation != ByteCodeGenerator::RootObjectRegister);
7979
7983
7980
- EmitMethodFld(isRoot, isScoped, pnode->location, callObjLocation, propertyId, byteCodeGenerator, funcInfo, registerCacheIdForCall);
7984
+ EmitMethodFld(isRoot, isScoped, pnodeCall->isNullPropagating, pnode->location, callObjLocation, propertyId, byteCodeGenerator, funcInfo, registerCacheIdForCall);
7981
7985
}
7982
7986
7983
7987
// lhs.apply(this, arguments);
@@ -8004,7 +8008,7 @@ void EmitApplyCall(ParseNodeCall* pnodeCall, ByteCodeGenerator* byteCodeGenerato
8004
8008
// call for apply, we won't remove the entry for "apply" cacheId from
8005
8009
// ByteCodeWriter::callRegToLdFldCacheIndexMap, which is contrary to our assumption that we would
8006
8010
// have removed an entry from a map upon seeing its corresponding call.
8007
- EmitMethodFld(applyNode, funcNode->location, propertyId, byteCodeGenerator, funcInfo, false /*registerCacheIdForCall*/);
8011
+ EmitMethodFld(pnodeCall, applyNode, funcNode->location, propertyId, byteCodeGenerator, funcInfo, false /*registerCacheIdForCall*/);
8008
8012
8009
8013
Symbol *argSym = funcInfo->GetArgumentsSymbol();
8010
8014
Assert(argSym && argSym->IsArguments());
@@ -8107,6 +8111,7 @@ void EmitCallTargetNoEvalComponents(
8107
8111
}
8108
8112
8109
8113
void EmitCallTarget(
8114
+ ParseNodeCall *pnodeCall,
8110
8115
ParseNode *pnodeTarget,
8111
8116
BOOL fSideEffectArgs,
8112
8117
Js::RegSlot *thisLocation,
@@ -8131,7 +8136,7 @@ void EmitCallTarget(
8131
8136
{
8132
8137
case knopOptChain: {
8133
8138
EmitOptionalChainWrapper(pnodeTarget->AsParseNodeUni(), byteCodeGenerator, funcInfo, [&](ParseNodePtr innerNode) {
8134
- EmitCallTarget(innerNode, fSideEffectArgs, thisLocation, releaseThisLocation, callObjLocation, byteCodeGenerator, funcInfo, callApplyCallSiteId);
8139
+ EmitCallTarget(pnodeCall, innerNode, fSideEffectArgs, thisLocation, releaseThisLocation, callObjLocation, byteCodeGenerator, funcInfo, callApplyCallSiteId);
8135
8140
});
8136
8141
break;
8137
8142
}
@@ -8180,7 +8185,7 @@ void EmitCallTarget(
8180
8185
{
8181
8186
*thisLocation = pnodeBinTarget->pnode1->location;
8182
8187
EmitNullPropagation(pnodeBinTarget->pnode1->location, byteCodeGenerator, funcInfo, pnodeBinTarget->isNullPropagating);
8183
- EmitMethodFld(pnodeBinTarget, protoLocation, propertyId, byteCodeGenerator, funcInfo);
8188
+ EmitMethodFld(pnodeCall, pnodeBinTarget, protoLocation, propertyId, byteCodeGenerator, funcInfo);
8184
8189
}
8185
8190
8186
8191
break;
@@ -8248,7 +8253,7 @@ void EmitCallTarget(
8248
8253
{
8249
8254
// Load the call target as a property of the instance.
8250
8255
Js::PropertyId propertyId = pnodeNameTarget->PropertyIdFromNameNode();
8251
- EmitMethodFld(pnodeNameTarget, *callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8256
+ EmitMethodFld(pnodeCall, pnodeNameTarget, *callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8252
8257
break;
8253
8258
}
8254
8259
}
@@ -8404,7 +8409,7 @@ void EmitCallInstrNoEvalComponents(
8404
8409
Assert(pnodeTarget->AsParseNodeBin()->pnode2->nop == knopName);
8405
8410
Js::PropertyId propertyId = pnodeTarget->AsParseNodeBin()->pnode2->AsParseNodeName()->PropertyIdFromNameNode();
8406
8411
8407
- EmitMethodFld(pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8412
+ EmitMethodFld(pnodeCall, pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8408
8413
EmitCallI(pnodeCall, /*fEvaluateComponents*/ FALSE, fIsEval, fHasNewTarget, actualArgCount, byteCodeGenerator, funcInfo, callSiteId, spreadIndices);
8409
8414
}
8410
8415
break;
@@ -8428,7 +8433,7 @@ void EmitCallInstrNoEvalComponents(
8428
8433
funcInfo->ReleaseTmpRegister(callObjLocation);
8429
8434
8430
8435
Js::PropertyId propertyId = pnodeTarget->AsParseNodeName()->PropertyIdFromNameNode();
8431
- EmitMethodFld(pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8436
+ EmitMethodFld(pnodeCall, pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8432
8437
EmitCallI(pnodeCall, /*fEvaluateComponents*/ FALSE, fIsEval, fHasNewTarget, actualArgCount, byteCodeGenerator, funcInfo, callSiteId, spreadIndices);
8433
8438
break;
8434
8439
}
@@ -8653,7 +8658,7 @@ void EmitCall(
8653
8658
}
8654
8659
else
8655
8660
{
8656
- EmitCallTarget(pnodeTarget, fSideEffectArgs, &thisLocation, &releaseThisLocation, &callObjLocation, byteCodeGenerator, funcInfo, &callApplyCallSiteId);
8661
+ EmitCallTarget(pnodeCall, pnodeTarget, fSideEffectArgs, &thisLocation, &releaseThisLocation, &callObjLocation, byteCodeGenerator, funcInfo, &callApplyCallSiteId);
8657
8662
}
8658
8663
}
8659
8664
@@ -8705,7 +8710,7 @@ void EmitInvoke(
8705
8710
ByteCodeGenerator* byteCodeGenerator,
8706
8711
FuncInfo* funcInfo)
8707
8712
{
8708
- EmitMethodFld(false, false, location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8713
+ EmitMethodFld(false, false, false, location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8709
8714
8710
8715
funcInfo->StartRecordingOutArgs(1);
8711
8716
@@ -8725,7 +8730,7 @@ void EmitInvoke(
8725
8730
FuncInfo* funcInfo,
8726
8731
Js::RegSlot arg1Location)
8727
8732
{
8728
- EmitMethodFld(false, false, location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8733
+ EmitMethodFld(false, false, false, location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8729
8734
8730
8735
funcInfo->StartRecordingOutArgs(2);
8731
8736
0 commit comments