@@ -3387,6 +3387,15 @@ bool Instr::CanHaveArgOutChain() const
3387
3387
this ->m_opcode == Js::OpCode::NewScObjArraySpread;
3388
3388
}
3389
3389
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
+
3390
3399
bool Instr::HasEmptyArgOutChain (IR::Instr** startCallInstrOut)
3391
3400
{
3392
3401
Assert (CanHaveArgOutChain ());
@@ -3408,6 +3417,22 @@ bool Instr::HasEmptyArgOutChain(IR::Instr** startCallInstrOut)
3408
3417
return false ;
3409
3418
}
3410
3419
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
+
3411
3436
bool Instr::HasFixedFunctionAddressTarget () const
3412
3437
{
3413
3438
Assert (
@@ -3417,14 +3442,96 @@ bool Instr::HasFixedFunctionAddressTarget() const
3417
3442
this ->m_opcode == Js::OpCode::NewScObjectSpread ||
3418
3443
this ->m_opcode == Js::OpCode::NewScObjArray ||
3419
3444
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);
3421
3447
return
3422
3448
this ->GetSrc1 () != nullptr &&
3423
3449
this ->GetSrc1 ()->IsAddrOpnd () &&
3424
3450
this ->GetSrc1 ()->AsAddrOpnd ()->GetAddrOpndKind () == IR::AddrOpndKind::AddrOpndKindDynamicVar &&
3425
3451
this ->GetSrc1 ()->AsAddrOpnd ()->m_isFunction ;
3426
3452
}
3427
3453
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
+
3428
3535
bool Instr::TransfersSrcValue ()
3429
3536
{
3430
3537
// Return whether the instruction transfers a value to the destination.
@@ -3635,7 +3742,7 @@ uint Instr::GetArgOutCount(bool getInterpreterArgOutCount)
3635
3742
opcode == Js::OpCode::EndCallForPolymorphicInlinee || opcode == Js::OpCode::LoweredStartCall);
3636
3743
3637
3744
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 ()
3639
3746
? this ->GetSrc1 ()->AsIntConstOpnd ()->AsUint32 ()
3640
3747
: this ->GetSrc2 ()->AsIntConstOpnd ()->AsUint32 ();
3641
3748
0 commit comments