@@ -558,7 +558,7 @@ void LinearScanMD::GeneratorBailIn::InsertRestoreSymbols(
558558 StackSym* stackSym = this ->func ->m_symTable ->FindStackSym (symId);
559559 Lifetime* lifetime = stackSym->scratch .linearScan .lifetime ;
560560
561- if (this ->NeedsReloadingValueWhenBailIn (stackSym))
561+ if (this ->NeedsReloadingValueWhenBailIn (stackSym, lifetime ))
562562 {
563563 Js::RegSlot regSlot = stackSym->GetByteCodeRegSlot ();
564564 IR::Opnd* srcOpnd = IR::IndirOpnd::New (
@@ -570,11 +570,62 @@ void LinearScanMD::GeneratorBailIn::InsertRestoreSymbols(
570570
571571 if (lifetime->isSpilled )
572572 {
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 );
574578 }
575579 else
576580 {
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 );
578629 }
579630 }
580631 else
@@ -595,12 +646,18 @@ void LinearScanMD::GeneratorBailIn::InsertRestoreSymbols(
595646 NEXT_BITSET_IN_SPARSEBV;
596647}
597648
598- bool LinearScanMD::GeneratorBailIn::NeedsReloadingValueWhenBailIn (StackSym* sym) const
649+ bool LinearScanMD::GeneratorBailIn::NeedsReloadingValueWhenBailIn (StackSym* sym, Lifetime* lifetime ) const
599650{
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 ())
602652 {
603- return false ;
653+ if (this ->func ->GetJITFunctionBody ()->RegIsConstant (sym->GetByteCodeRegSlot ()))
654+ {
655+ return false ;
656+ }
657+ else
658+ {
659+ return !lifetime->isSpilled ;
660+ }
604661 }
605662
606663 // 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)
614671 return !this ->initializedRegs .Test (sym->GetByteCodeRegSlot ());
615672}
616673
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-
671674IR::SymOpnd* LinearScanMD::GeneratorBailIn::CreateGeneratorObjectOpnd () const
672675{
673676 StackSym* sym = StackSym::NewParamSlotSym (1 , this ->func );
0 commit comments