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