@@ -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,96 @@ 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+
3482+ // Looking for the opcode GenCtorObj in currArgOutInstrValDef.
3483+ currArgOutInstrValDef = currArgOutInstr->GetSrc1 ()->GetStackSym ()->GetInstrDef ();
3484+ Assert (currArgOutInstrValDef);
3485+ if (currArgOutInstrValDef->m_opcode == Js::OpCode::BytecodeArgOutCapture)
3486+ {
3487+ if (currArgOutInstrValDef->GetSrc1 ()->GetStackSym ())
3488+ {
3489+ // Indirection through BytecodeArgOutCapture.
3490+ currArgOutInstrValDef = currArgOutInstrValDef->GetSrc1 ()->GetStackSym ()->GetInstrDef ();
3491+ }
3492+ Assert (currArgOutInstrValDef);
3493+ }
3494+ } while (currArgOutInstrValDef->m_opcode != Js::OpCode::GenCtorObj);
3495+ return currArgOutInstrValDef;
3496+ }
3497+
3498+ Opnd* Instr::GetArgOutVal (uint argIndex)
3499+ {
3500+ Assert (IsNewScObjCallVariantInstr ());
3501+ Instr* currArgOutInstr = this ;
3502+ do
3503+ {
3504+ Assert (currArgOutInstr->GetSrc2 ());
3505+ currArgOutInstr = currArgOutInstr->GetSrc2 ()->GetStackSym ()->GetInstrDef ();
3506+ Assert (currArgOutInstr);
3507+ if (currArgOutInstr->m_opcode == Js::OpCode::StartCall)
3508+ {
3509+ // argIndex is larger than this argOutChain's length.
3510+ return nullptr ;
3511+ }
3512+
3513+ if (currArgOutInstr->m_opcode == Js::OpCode::LdSpreadIndices)
3514+ {
3515+ // This instr is a redirection, move on to next instr.
3516+ continue ;
3517+ }
3518+ Assert (currArgOutInstr->m_opcode == Js::OpCode::ArgOut_A);
3519+
3520+ if (argIndex > 0 )
3521+ {
3522+ argIndex--;
3523+ }
3524+ } while (argIndex > 0 );
3525+
3526+ Opnd* argOutVal = currArgOutInstr->GetSrc1 ();
3527+ if (argOutVal->GetStackSym ()->m_instrDef ->m_opcode == Js::OpCode::BytecodeArgOutCapture)
3528+ {
3529+ argOutVal = argOutVal->GetStackSym ()->m_instrDef ->GetSrc1 ();
3530+ }
3531+
3532+ return argOutVal;
3533+ }
3534+
34283535bool Instr::TransfersSrcValue ()
34293536{
34303537 // Return whether the instruction transfers a value to the destination.
@@ -3635,7 +3742,7 @@ uint Instr::GetArgOutCount(bool getInterpreterArgOutCount)
36353742 opcode == Js::OpCode::EndCallForPolymorphicInlinee || opcode == Js::OpCode::LoweredStartCall);
36363743
36373744 Assert (!getInterpreterArgOutCount || opcode == Js::OpCode::StartCall);
3638- uint argOutCount = !this ->GetSrc2 () || !getInterpreterArgOutCount || m_func->GetJITFunctionBody ()->IsAsmJsMode ()
3745+ uint argOutCount = !this ->GetSrc2 () || !getInterpreterArgOutCount || m_func->GetJITFunctionBody ()->IsAsmJsMode ()
36393746 ? this ->GetSrc1 ()->AsIntConstOpnd ()->AsUint32 ()
36403747 : this ->GetSrc2 ()->AsIntConstOpnd ()->AsUint32 ();
36413748
0 commit comments