@@ -81,7 +81,7 @@ static void EmitOptionalChainWrapper(ParseNodeUni *pnodeOptChain, ByteCodeGenera
81
81
byteCodeGenerator->Writer ()->Br (doneLabel);
82
82
}
83
83
84
- byteCodeGenerator->Writer ()->MarkLabel (skipLabel);
84
+ byteCodeGenerator->Writer ()->MarkLabel (skipLabel);
85
85
86
86
if (pnodeOptChain->isUsed )
87
87
{
@@ -7928,10 +7928,14 @@ Js::ArgSlot EmitNewObjectOfConstants(
7928
7928
return actualArgCount;
7929
7929
}
7930
7930
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 )
7932
7932
{
7933
7933
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)
7935
7939
{
7936
7940
if (callObjLocation == funcInfo->frameObjRegister )
7937
7941
{
@@ -7971,15 +7975,15 @@ void EmitMethodFld(bool isRoot, bool isScoped, Js::RegSlot location, Js::RegSlot
7971
7975
}
7972
7976
}
7973
7977
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 )
7975
7979
{
7976
7980
// Load a call target of the form x.y(). (Call target may be a plain knopName if we're getting it from
7977
7981
// the global object, etc.)
7978
7982
bool isRoot = pnode->nop == knopName && (pnode->AsParseNodeName ()->sym == nullptr || pnode->AsParseNodeName ()->sym ->GetIsGlobal ());
7979
7983
bool isScoped = (byteCodeGenerator->GetFlags () & fscrEval) != 0 ||
7980
7984
(isRoot && callObjLocation != ByteCodeGenerator::RootObjectRegister);
7981
7985
7982
- EmitMethodFld (isRoot, isScoped, pnode->location , callObjLocation, propertyId, byteCodeGenerator, funcInfo, registerCacheIdForCall);
7986
+ EmitMethodFld (isRoot, isScoped, pnodeCall-> isNullPropagating , pnode->location , callObjLocation, propertyId, byteCodeGenerator, funcInfo, registerCacheIdForCall);
7983
7987
}
7984
7988
7985
7989
// lhs.apply(this, arguments);
@@ -8006,7 +8010,7 @@ void EmitApplyCall(ParseNodeCall* pnodeCall, ByteCodeGenerator* byteCodeGenerato
8006
8010
// call for apply, we won't remove the entry for "apply" cacheId from
8007
8011
// ByteCodeWriter::callRegToLdFldCacheIndexMap, which is contrary to our assumption that we would
8008
8012
// 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*/ );
8010
8014
8011
8015
Symbol *argSym = funcInfo->GetArgumentsSymbol ();
8012
8016
Assert (argSym && argSym->IsArguments ());
@@ -8109,6 +8113,7 @@ void EmitCallTargetNoEvalComponents(
8109
8113
}
8110
8114
8111
8115
void EmitCallTarget (
8116
+ ParseNodeCall *pnodeCall,
8112
8117
ParseNode *pnodeTarget,
8113
8118
BOOL fSideEffectArgs ,
8114
8119
Js::RegSlot *thisLocation,
@@ -8133,7 +8138,7 @@ void EmitCallTarget(
8133
8138
{
8134
8139
case knopOptChain: {
8135
8140
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);
8137
8142
});
8138
8143
break ;
8139
8144
}
@@ -8182,7 +8187,7 @@ void EmitCallTarget(
8182
8187
{
8183
8188
*thisLocation = pnodeBinTarget->pnode1 ->location ;
8184
8189
EmitNullPropagation (pnodeBinTarget->pnode1 ->location , byteCodeGenerator, funcInfo, pnodeBinTarget->isNullPropagating );
8185
- EmitMethodFld (pnodeBinTarget, protoLocation, propertyId, byteCodeGenerator, funcInfo);
8190
+ EmitMethodFld (pnodeCall, pnodeBinTarget, protoLocation, propertyId, byteCodeGenerator, funcInfo);
8186
8191
}
8187
8192
8188
8193
break ;
@@ -8250,7 +8255,7 @@ void EmitCallTarget(
8250
8255
{
8251
8256
// Load the call target as a property of the instance.
8252
8257
Js::PropertyId propertyId = pnodeNameTarget->PropertyIdFromNameNode ();
8253
- EmitMethodFld (pnodeNameTarget, *callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8258
+ EmitMethodFld (pnodeCall, pnodeNameTarget, *callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8254
8259
break ;
8255
8260
}
8256
8261
}
@@ -8406,7 +8411,7 @@ void EmitCallInstrNoEvalComponents(
8406
8411
Assert (pnodeTarget->AsParseNodeBin ()->pnode2 ->nop == knopName);
8407
8412
Js::PropertyId propertyId = pnodeTarget->AsParseNodeBin ()->pnode2 ->AsParseNodeName ()->PropertyIdFromNameNode ();
8408
8413
8409
- EmitMethodFld (pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8414
+ EmitMethodFld (pnodeCall, pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8410
8415
EmitCallI (pnodeCall, /* fEvaluateComponents*/ FALSE , fIsEval , fHasNewTarget , actualArgCount, byteCodeGenerator, funcInfo, callSiteId, spreadIndices);
8411
8416
}
8412
8417
break ;
@@ -8430,7 +8435,7 @@ void EmitCallInstrNoEvalComponents(
8430
8435
funcInfo->ReleaseTmpRegister (callObjLocation);
8431
8436
8432
8437
Js::PropertyId propertyId = pnodeTarget->AsParseNodeName ()->PropertyIdFromNameNode ();
8433
- EmitMethodFld (pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8438
+ EmitMethodFld (pnodeCall, pnodeTarget, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8434
8439
EmitCallI (pnodeCall, /* fEvaluateComponents*/ FALSE , fIsEval , fHasNewTarget , actualArgCount, byteCodeGenerator, funcInfo, callSiteId, spreadIndices);
8435
8440
break ;
8436
8441
}
@@ -8655,7 +8660,7 @@ void EmitCall(
8655
8660
}
8656
8661
else
8657
8662
{
8658
- EmitCallTarget (pnodeTarget, fSideEffectArgs , &thisLocation, &releaseThisLocation, &callObjLocation, byteCodeGenerator, funcInfo, &callApplyCallSiteId);
8663
+ EmitCallTarget (pnodeCall, pnodeTarget, fSideEffectArgs , &thisLocation, &releaseThisLocation, &callObjLocation, byteCodeGenerator, funcInfo, &callApplyCallSiteId);
8659
8664
}
8660
8665
}
8661
8666
@@ -8707,7 +8712,7 @@ void EmitInvoke(
8707
8712
ByteCodeGenerator* byteCodeGenerator,
8708
8713
FuncInfo* funcInfo)
8709
8714
{
8710
- EmitMethodFld (false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8715
+ EmitMethodFld (false , false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8711
8716
8712
8717
funcInfo->StartRecordingOutArgs (1 );
8713
8718
@@ -8727,7 +8732,7 @@ void EmitInvoke(
8727
8732
FuncInfo* funcInfo,
8728
8733
Js::RegSlot arg1Location)
8729
8734
{
8730
- EmitMethodFld (false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8735
+ EmitMethodFld (false , false , false , location, callObjLocation, propertyId, byteCodeGenerator, funcInfo);
8731
8736
8732
8737
funcInfo->StartRecordingOutArgs (2 );
8733
8738
0 commit comments