@@ -3387,6 +3387,15 @@ bool Instr::CanHaveArgOutChain() const
33873387 this ->m_opcode == Js::OpCode::NewScObjArraySpread;
33883388}
33893389
3390+ bool Instr::IsNewScObjCallVariantInstr ()
3391+ {
3392+ return
3393+ this ->m_opcode == Js::OpCode::NewScObject ||
3394+ this ->m_opcode == Js::OpCode::NewScObjectSpread ||
3395+ this ->m_opcode == Js::OpCode::NewScObjArray ||
3396+ this ->m_opcode == Js::OpCode::NewScObjArraySpread;
3397+ }
3398+
33903399bool Instr::HasEmptyArgOutChain (IR::Instr** startCallInstrOut)
33913400{
33923401 Assert (CanHaveArgOutChain ());
@@ -3408,6 +3417,22 @@ bool Instr::HasEmptyArgOutChain(IR::Instr** startCallInstrOut)
34083417 return false ;
34093418}
34103419
3420+ uint Instr::ArgOutChainLength ()
3421+ {
3422+ Assert (CanHaveArgOutChain ());
3423+
3424+ uint length = 0 ;
3425+ Instr* currArgOutInstr = GetSrc2 ()->GetStackSym ()->GetInstrDef ();
3426+
3427+ while (currArgOutInstr->m_opcode != Js::OpCode::StartCall)
3428+ {
3429+ length++;
3430+ currArgOutInstr = currArgOutInstr->GetSrc2 ()->GetStackSym ()->GetInstrDef ();
3431+ }
3432+
3433+ return length;
3434+ }
3435+
34113436bool Instr::HasFixedFunctionAddressTarget () const
34123437{
34133438 Assert (
@@ -3417,14 +3442,90 @@ bool Instr::HasFixedFunctionAddressTarget() const
34173442 this ->m_opcode == Js::OpCode::NewScObjectSpread ||
34183443 this ->m_opcode == Js::OpCode::NewScObjArray ||
34193444 this ->m_opcode == Js::OpCode::NewScObjArraySpread ||
3420- this ->m_opcode == Js::OpCode::NewScObjectNoCtor);
3445+ this ->m_opcode == Js::OpCode::NewScObjectNoCtor ||
3446+ this ->m_opcode == Js::OpCode::GenCtorObj);
34213447 return
34223448 this ->GetSrc1 () != nullptr &&
34233449 this ->GetSrc1 ()->IsAddrOpnd () &&
34243450 this ->GetSrc1 ()->AsAddrOpnd ()->GetAddrOpndKind () == IR::AddrOpndKind::AddrOpndKindDynamicVar &&
34253451 this ->GetSrc1 ()->AsAddrOpnd ()->m_isFunction ;
34263452}
34273453
3454+ Instr* Instr::GetGenCtorInstr ()
3455+ {
3456+ Assert (IsNewScObjCallVariantInstr ());
3457+ Instr* currArgOutInstr = this ;
3458+ Instr* currArgOutInstrValDef = this ;
3459+ do
3460+ {
3461+ // TODO: should use helper method here? GetNextInstr?
3462+ Assert (currArgOutInstr->GetSrc2 ());
3463+ currArgOutInstr = currArgOutInstr->GetSrc2 ()->GetStackSym ()->GetInstrDef ();
3464+ Assert (currArgOutInstr);
3465+ if (currArgOutInstr->m_opcode == Js::OpCode::GenCtorObj)
3466+ {
3467+ return currArgOutInstr;
3468+ }
3469+ if (currArgOutInstr->m_opcode == Js::OpCode::LdSpreadIndices)
3470+ {
3471+ // This instr is a redirection, move on to next instr.
3472+ continue ;
3473+ }
3474+ Assert (currArgOutInstr->m_opcode == Js::OpCode::ArgOut_A);
3475+ if (currArgOutInstr->GetSrc1 ()->IsAddrOpnd ())
3476+ {
3477+ // This instr's src1 is not a symbol, thus it does not have a def instr
3478+ // and thus it cannot be from a GenCtorObj instr.
3479+ continue ;
3480+ }
3481+ currArgOutInstrValDef = currArgOutInstr->GetSrc1 ()->GetStackSym ()->GetInstrDef ();
3482+ Assert (currArgOutInstrValDef);
3483+ if (currArgOutInstrValDef->m_opcode == Js::OpCode::BytecodeArgOutCapture)
3484+ {
3485+ currArgOutInstrValDef = currArgOutInstrValDef->GetSrc1 ()->GetStackSym ()->GetInstrDef ();
3486+ Assert (currArgOutInstrValDef);
3487+ }
3488+ } while (currArgOutInstrValDef->m_opcode != Js::OpCode::GenCtorObj);
3489+ return currArgOutInstrValDef;
3490+ }
3491+
3492+ Opnd* Instr::GetArgOutVal (uint argIndex)
3493+ {
3494+ Assert (IsNewScObjCallVariantInstr ());
3495+ Instr* currArgOutInstr = this ;
3496+ do
3497+ {
3498+ Assert (currArgOutInstr->GetSrc2 ());
3499+ currArgOutInstr = currArgOutInstr->GetSrc2 ()->GetStackSym ()->GetInstrDef ();
3500+ Assert (currArgOutInstr);
3501+ if (currArgOutInstr->m_opcode == Js::OpCode::StartCall)
3502+ {
3503+ // argIndex is larger than this argOutChain's length.
3504+ return nullptr ;
3505+ }
3506+
3507+ if (currArgOutInstr->m_opcode == Js::OpCode::LdSpreadIndices)
3508+ {
3509+ // This instr is a redirection, move on to next instr.
3510+ continue ;
3511+ }
3512+ Assert (currArgOutInstr->m_opcode == Js::OpCode::ArgOut_A);
3513+
3514+ if (argIndex > 0 )
3515+ {
3516+ argIndex--;
3517+ }
3518+ } while (argIndex > 0 );
3519+
3520+ Opnd* argOutVal = currArgOutInstr->GetSrc1 ();
3521+ if (argOutVal->GetStackSym ()->m_instrDef ->m_opcode == Js::OpCode::BytecodeArgOutCapture)
3522+ {
3523+ argOutVal = argOutVal->GetStackSym ()->m_instrDef ->GetSrc1 ();
3524+ }
3525+
3526+ return argOutVal;
3527+ }
3528+
34283529bool Instr::TransfersSrcValue ()
34293530{
34303531 // Return whether the instruction transfers a value to the destination.
@@ -3635,7 +3736,7 @@ uint Instr::GetArgOutCount(bool getInterpreterArgOutCount)
36353736 opcode == Js::OpCode::EndCallForPolymorphicInlinee || opcode == Js::OpCode::LoweredStartCall);
36363737
36373738 Assert (!getInterpreterArgOutCount || opcode == Js::OpCode::StartCall);
3638- uint argOutCount = !this ->GetSrc2 () || !getInterpreterArgOutCount || m_func->GetJITFunctionBody ()->IsAsmJsMode ()
3739+ uint argOutCount = !this ->GetSrc2 () || !getInterpreterArgOutCount || m_func->GetJITFunctionBody ()->IsAsmJsMode ()
36393740 ? this ->GetSrc1 ()->AsIntConstOpnd ()->AsUint32 ()
36403741 : this ->GetSrc2 ()->AsIntConstOpnd ()->AsUint32 ();
36413742
0 commit comments