@@ -558,7 +558,7 @@ void LinearScanMD::GeneratorBailIn::InsertRestoreSymbols(
558
558
StackSym* stackSym = this ->func ->m_symTable ->FindStackSym (symId);
559
559
Lifetime* lifetime = stackSym->scratch .linearScan .lifetime ;
560
560
561
- if (this ->NeedsReloadingValueWhenBailIn (stackSym))
561
+ if (this ->NeedsReloadingValueWhenBailIn (stackSym, lifetime ))
562
562
{
563
563
Js::RegSlot regSlot = stackSym->GetByteCodeRegSlot ();
564
564
IR::Opnd* srcOpnd = IR::IndirOpnd::New (
@@ -570,11 +570,62 @@ void LinearScanMD::GeneratorBailIn::InsertRestoreSymbols(
570
570
571
571
if (lifetime->isSpilled )
572
572
{
573
- this ->InsertRestoreStackSymbol (stackSym, srcOpnd, insertionPoint);
573
+ Assert (!stackSym->IsConst ());
574
+ // Stack restores require an extra register since we can't move an indir directly to an indir on amd64
575
+ IR::SymOpnd* dstOpnd = IR::SymOpnd::New (stackSym, stackSym->GetType (), this ->func );
576
+ LinearScan::InsertMove (this ->rcxRegOpnd , srcOpnd, insertionPoint.instrInsertStackSym );
577
+ LinearScan::InsertMove (dstOpnd, this ->rcxRegOpnd , insertionPoint.instrInsertStackSym );
574
578
}
575
579
else
576
580
{
577
- this ->InsertRestoreRegSymbol (stackSym, srcOpnd, insertionPoint);
581
+ // Register restores must come after stack restores so that we have RAX and RCX free to
582
+ // use for stack restores and further RAX must be restored last since it holds the
583
+ // pointer to the InterpreterStackFrame from which we are restoring values.
584
+ // We must also track these restores using RecordDef in case the symbols are spilled.
585
+
586
+ IR::Instr* instr;
587
+
588
+ if (stackSym->IsConst ())
589
+ {
590
+ instr = this ->linearScanMD ->linearScan ->InsertLoad (insertionPoint.instrInsertRegSym , stackSym, lifetime->reg );
591
+ }
592
+ else
593
+ {
594
+ IR::RegOpnd* dstRegOpnd = IR::RegOpnd::New (stackSym, stackSym->GetType (), this ->func );
595
+ dstRegOpnd->SetReg (lifetime->reg );
596
+ instr = LinearScan::InsertMove (dstRegOpnd, srcOpnd, insertionPoint.instrInsertRegSym );
597
+ }
598
+
599
+ if (insertionPoint.instrInsertRegSym == insertionPoint.instrInsertStackSym )
600
+ {
601
+ // This is the first register sym, make sure we don't insert stack stores
602
+ // after this instruction so we can ensure rax and rcx remain free to use
603
+ // for restoring spilled stack syms.
604
+ insertionPoint.instrInsertStackSym = instr;
605
+ }
606
+
607
+ if (lifetime->reg == RegRAX)
608
+ {
609
+ // Ensure rax is restored last
610
+ Assert (insertionPoint.instrInsertRegSym != insertionPoint.instrInsertStackSym );
611
+
612
+ insertionPoint.instrInsertRegSym = instr;
613
+
614
+ if (insertionPoint.raxRestoreInstr != nullptr )
615
+ {
616
+ AssertMsg (false , " this is unexpected until copy prop is enabled" );
617
+ // rax was mapped to multiple bytecode registers. Obviously only the first
618
+ // restore we do will work so change all following stores to `mov rax, rax`.
619
+ // We still need to keep them around for RecordDef in case the corresponding
620
+ // dst sym is spilled later on.
621
+ insertionPoint.raxRestoreInstr ->FreeSrc1 ();
622
+ insertionPoint.raxRestoreInstr ->SetSrc1 (this ->raxRegOpnd );
623
+ }
624
+
625
+ insertionPoint.raxRestoreInstr = instr;
626
+ }
627
+
628
+ this ->linearScanMD ->linearScan ->RecordDef (lifetime, instr, 0 );
578
629
}
579
630
}
580
631
else
@@ -595,12 +646,18 @@ void LinearScanMD::GeneratorBailIn::InsertRestoreSymbols(
595
646
NEXT_BITSET_IN_SPARSEBV;
596
647
}
597
648
598
- bool LinearScanMD::GeneratorBailIn::NeedsReloadingValueWhenBailIn (StackSym* sym) const
649
+ bool LinearScanMD::GeneratorBailIn::NeedsReloadingValueWhenBailIn (StackSym* sym, Lifetime* lifetime ) const
599
650
{
600
- // We load constant values before the generator resume jump table, no need to reload
601
- if (this ->func ->GetJITFunctionBody ()->RegIsConstant (sym->GetByteCodeRegSlot ()))
651
+ if (sym->IsConst ())
602
652
{
603
- return false ;
653
+ if (this ->func ->GetJITFunctionBody ()->RegIsConstant (sym->GetByteCodeRegSlot ()))
654
+ {
655
+ return false ;
656
+ }
657
+ else
658
+ {
659
+ return !lifetime->isSpilled ;
660
+ }
604
661
}
605
662
606
663
// If we have for-in in the generator, don't need to reload the symbol again as it is done
@@ -614,60 +671,6 @@ bool LinearScanMD::GeneratorBailIn::NeedsReloadingValueWhenBailIn(StackSym* sym)
614
671
return !this ->initializedRegs .Test (sym->GetByteCodeRegSlot ());
615
672
}
616
673
617
- void LinearScanMD::GeneratorBailIn::InsertRestoreRegSymbol (StackSym* stackSym, IR::Opnd* srcOpnd, BailInInsertionPoint& insertionPoint)
618
- {
619
- Lifetime* lifetime = stackSym->scratch .linearScan .lifetime ;
620
-
621
- // Register restores must come after stack restores so that we have RAX and RCX free to
622
- // use for stack restores and further RAX must be restored last since it holds the
623
- // pointer to the InterpreterStackFrame from which we are restoring values.
624
- // We must also track these restores using RecordDef in case the symbols are spilled.
625
-
626
- IR::RegOpnd* dstRegOpnd = IR::RegOpnd::New (stackSym, stackSym->GetType (), this ->func );
627
- dstRegOpnd->SetReg (lifetime->reg );
628
-
629
- IR::Instr* instr = LinearScan::InsertMove (dstRegOpnd, srcOpnd, insertionPoint.instrInsertRegSym );
630
-
631
- if (insertionPoint.instrInsertRegSym == insertionPoint.instrInsertStackSym )
632
- {
633
- // This is the first register sym, make sure we don't insert stack stores
634
- // after this instruction so we can ensure rax and rcx remain free to use
635
- // for restoring spilled stack syms.
636
- insertionPoint.instrInsertStackSym = instr;
637
- }
638
-
639
- if (lifetime->reg == RegRAX)
640
- {
641
- // Ensure rax is restored last
642
- Assert (insertionPoint.instrInsertRegSym != insertionPoint.instrInsertStackSym );
643
-
644
- insertionPoint.instrInsertRegSym = instr;
645
-
646
- if (insertionPoint.raxRestoreInstr != nullptr )
647
- {
648
- AssertMsg (false , " this is unexpected until copy prop is enabled" );
649
- // rax was mapped to multiple bytecode registers. Obviously only the first
650
- // restore we do will work so change all following stores to `mov rax, rax`.
651
- // We still need to keep them around for RecordDef in case the corresponding
652
- // dst sym is spilled later on.
653
- insertionPoint.raxRestoreInstr ->FreeSrc1 ();
654
- insertionPoint.raxRestoreInstr ->SetSrc1 (this ->raxRegOpnd );
655
- }
656
-
657
- insertionPoint.raxRestoreInstr = instr;
658
- }
659
-
660
- this ->linearScanMD ->linearScan ->RecordDef (lifetime, instr, 0 );
661
- }
662
-
663
- void LinearScanMD::GeneratorBailIn::InsertRestoreStackSymbol (StackSym* stackSym, IR::Opnd* srcOpnd, BailInInsertionPoint& insertionPoint)
664
- {
665
- // Stack restores require an extra register since we can't move an indir directly to an indir on amd64
666
- IR::SymOpnd* dstOpnd = IR::SymOpnd::New (stackSym, stackSym->GetType (), this ->func );
667
- LinearScan::InsertMove (this ->rcxRegOpnd , srcOpnd, insertionPoint.instrInsertStackSym );
668
- LinearScan::InsertMove (dstOpnd, this ->rcxRegOpnd , insertionPoint.instrInsertStackSym );
669
- }
670
-
671
674
IR::SymOpnd* LinearScanMD::GeneratorBailIn::CreateGeneratorObjectOpnd () const
672
675
{
673
676
StackSym* sym = StackSym::NewParamSlotSym (1 , this ->func );
0 commit comments