VirtualBox

Ignore:
Timestamp:
Aug 22, 2024 2:19:39 PM (3 months ago)
Author:
vboxsync
Message:

VMM/IEM: Record whether any of the branches of an IEM_MC_IF_XXX/IEM_MC_ELSE/IEM_MC_ENDIF block exits the TB and make use of that to skip the recompiler state consolidation in the IEM_MC_ENDIF handler (iemNativeEmitEndIf). This is a preparatory step for addressing todo 4. bugref:10720 bugref:10373

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h

    r105768 r105818  
    386386        /* As this code returns from the TB any pending register writes must be flushed. */
    387387        off = iemNativeRegFlushPendingWrites(pReNative, off);
     388
     389        /*
     390         * If we're in a conditional, mark the current branch as exiting so we
     391         * can disregard its state when we hit the IEM_MC_ENDIF.
     392         */
     393        uint8_t idxCondDepth = pReNative->cCondDepth;
     394        if (idxCondDepth)
     395        {
     396            idxCondDepth--;
     397            if (pReNative->aCondStack[idxCondDepth].fInElse)
     398                pReNative->aCondStack[idxCondDepth].fElseExitTb = true;
     399            else
     400                pReNative->aCondStack[idxCondDepth].fIfExitTb   = true;
     401        }
    388402
    389403        /*
     
    24642478    uint16_t const uCondSeqNo = ++pReNative->uCondSeqNo;
    24652479    pEntry->fInElse       = false;
     2480    pEntry->fIfExitTb     = false;
     2481    pEntry->fElseExitTb   = false;
    24662482    pEntry->idxLabelElse  = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Else, UINT32_MAX /*offWhere*/, uCondSeqNo);
    24672483    pEntry->idxLabelEndIf = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Endif, UINT32_MAX /*offWhere*/, uCondSeqNo);
     
    25522568    Assert(pReNative->cCondDepth > 0 && pReNative->cCondDepth <= RT_ELEMENTS(pReNative->aCondStack));
    25532569    PIEMNATIVECOND const pEntry = &pReNative->aCondStack[pReNative->cCondDepth - 1];
    2554 
    25552570#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
    25562571    Assert(pReNative->Core.offPc == 0);
    25572572#endif
     2573
     2574    /*
     2575     * If either of the branches exited the TB, we can take the state from the
     2576     * other branch and skip all the merging headache.
     2577     */
     2578    if (pEntry->fElseExitTb || pEntry->fIfExitTb)
     2579    {
     2580#ifdef VBOX_STRICT
     2581        Assert(pReNative->cCondDepth == 1);                 /* Assuming this only happens in simple conditional structures.  */
     2582        Assert(pEntry->fElseExitTb != pEntry->fIfExitTb);   /* Assuming we don't have any code where both branches exits. */
     2583        PCIEMNATIVECORESTATE const pExitCoreState = pEntry->fIfExitTb && pEntry->fInElse
     2584                                                  ? &pEntry->IfFinalState : &pReNative->Core;
     2585# ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     2586        Assert(pExitCoreState->bmGstRegShadowDirty == 0);
     2587# endif
     2588# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     2589        Assert(pExitCoreState->offPc == 0);
     2590# endif
     2591        RT_NOREF(pExitCoreState);
     2592#endif
     2593
     2594        if (!pEntry->fIfExitTb)
     2595        {
     2596            Assert(pEntry->fInElse);
     2597            pReNative->Core = pEntry->IfFinalState;
     2598        }
     2599    }
     2600    else
     2601    {
    25582602#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
    2559     /* Writeback any dirty shadow registers (else branch). */
    2560     /** @todo r=aeichner Possible optimization is to only writeback guest registers which became dirty
    2561      *                   in one of the branches and leave guest registers already dirty before the start of the if
    2562      *                   block alone. */
    2563     off = iemNativeRegFlushDirtyGuest(pReNative, off);
    2564 #endif
    2565 
    2566     /*
    2567      * Now we have find common group with the core state at the end of the
    2568      * if-final.  Use the smallest common denominator and just drop anything
    2569      * that isn't the same in both states.
    2570      */
    2571     /** @todo We could, maybe, shuffle registers around if we thought it helpful,
    2572      *        which is why we're doing this at the end of the else-block.
    2573      *        But we'd need more info about future for that to be worth the effort. */
    2574     PCIEMNATIVECORESTATE const pOther = pEntry->fInElse ? &pEntry->IfFinalState : &pEntry->InitialState;
     2603        /* Writeback any dirty shadow registers (else branch). */
     2604        /** @todo r=aeichner Possible optimization is to only writeback guest registers which became dirty
     2605         *                   in one of the branches and leave guest registers already dirty before the start of the if
     2606         *                   block alone. */
     2607        off = iemNativeRegFlushDirtyGuest(pReNative, off);
     2608#endif
     2609
     2610        /*
     2611         * Now we have find common group with the core state at the end of the
     2612         * if-final.  Use the smallest common denominator and just drop anything
     2613         * that isn't the same in both states.
     2614         */
     2615        /** @todo We could, maybe, shuffle registers around if we thought it helpful,
     2616         *        which is why we're doing this at the end of the else-block.
     2617         *        But we'd need more info about future for that to be worth the effort. */
     2618        PCIEMNATIVECORESTATE const pOther = pEntry->fInElse ? &pEntry->IfFinalState : &pEntry->InitialState;
    25752619#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
    2576     Assert(   pOther->bmGstRegShadowDirty == 0
    2577            && pReNative->Core.bmGstRegShadowDirty == 0);
    2578 #endif
    2579 
    2580     if (memcmp(&pReNative->Core, pOther, sizeof(*pOther)) != 0)
    2581     {
    2582         /* shadow guest stuff first. */
    2583         uint64_t fGstRegs = pReNative->Core.bmGstRegShadows;
    2584         if (fGstRegs)
     2620        Assert(   pOther->bmGstRegShadowDirty == 0
     2621               && pReNative->Core.bmGstRegShadowDirty == 0);
     2622#endif
     2623
     2624        if (memcmp(&pReNative->Core, pOther, sizeof(*pOther)) != 0)
    25852625        {
    2586             Assert(pReNative->Core.bmHstRegsWithGstShadow != 0);
    2587             do
     2626            /* shadow guest stuff first. */
     2627            uint64_t fGstRegs = pReNative->Core.bmGstRegShadows;
     2628            if (fGstRegs)
    25882629            {
    2589                 unsigned idxGstReg = ASMBitFirstSetU64(fGstRegs) - 1;
    2590                 fGstRegs &= ~RT_BIT_64(idxGstReg);
    2591 
    2592                 uint8_t const idxHstReg = pReNative->Core.aidxGstRegShadows[idxGstReg];
    2593                 if (  !(pOther->bmGstRegShadows & RT_BIT_64(idxGstReg))
    2594                     || idxHstReg != pOther->aidxGstRegShadows[idxGstReg])
     2630                Assert(pReNative->Core.bmHstRegsWithGstShadow != 0);
     2631                do
    25952632                {
    2596                     Log12(("iemNativeEmitEndIf: dropping gst %s from hst %s\n",
    2597                            g_aGstShadowInfo[idxGstReg].pszName, g_apszIemNativeHstRegNames[idxHstReg]));
     2633                    unsigned idxGstReg = ASMBitFirstSetU64(fGstRegs) - 1;
     2634                    fGstRegs &= ~RT_BIT_64(idxGstReg);
     2635
     2636                    uint8_t const idxHstReg = pReNative->Core.aidxGstRegShadows[idxGstReg];
     2637                    if (  !(pOther->bmGstRegShadows & RT_BIT_64(idxGstReg))
     2638                        || idxHstReg != pOther->aidxGstRegShadows[idxGstReg])
     2639                    {
     2640                        Log12(("iemNativeEmitEndIf: dropping gst %s from hst %s\n",
     2641                               g_aGstShadowInfo[idxGstReg].pszName, g_apszIemNativeHstRegNames[idxHstReg]));
    25982642
    25992643#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
    2600                     /* Writeback any dirty shadow registers we are about to unshadow. */
    2601                     off = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, off, idxHstReg);
    2602 #endif
    2603                     iemNativeRegClearGstRegShadowing(pReNative, idxHstReg, off);
    2604                 }
    2605             } while (fGstRegs);
     2644                        /* Writeback any dirty shadow registers we are about to unshadow. */
     2645                        off = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, off, idxHstReg);
     2646#endif
     2647                        iemNativeRegClearGstRegShadowing(pReNative, idxHstReg, off);
     2648                    }
     2649                } while (fGstRegs);
     2650            }
     2651            else
     2652            {
     2653                Assert(pReNative->Core.bmHstRegsWithGstShadow == 0);
     2654#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     2655                Assert(pReNative->Core.bmGstRegShadowDirty == 0);
     2656#endif
     2657            }
     2658
     2659            /* Check variables next. For now we must require them to be identical
     2660               or stuff we can recreate. */
     2661            Assert(pReNative->Core.u64ArgVars == pOther->u64ArgVars);
     2662            uint32_t fVars = pReNative->Core.bmVars | pOther->bmVars;
     2663            if (fVars)
     2664            {
     2665                uint32_t const fVarsMustRemove = pReNative->Core.bmVars ^ pOther->bmVars;
     2666                do
     2667                {
     2668                    unsigned idxVar = ASMBitFirstSetU32(fVars) - 1;
     2669                    fVars &= ~RT_BIT_32(idxVar);
     2670
     2671                    if (!(fVarsMustRemove & RT_BIT_32(idxVar)))
     2672                    {
     2673                        if (pReNative->Core.aVars[idxVar].idxReg == pOther->aVars[idxVar].idxReg)
     2674                            continue;
     2675                        if (pReNative->Core.aVars[idxVar].enmKind != kIemNativeVarKind_Stack)
     2676                        {
     2677                            uint8_t const idxHstReg = pReNative->Core.aVars[idxVar].idxReg;
     2678                            if (idxHstReg != UINT8_MAX)
     2679                            {
     2680                                pReNative->Core.bmHstRegs &= ~RT_BIT_32(idxHstReg);
     2681                                pReNative->Core.aVars[idxVar].idxReg = UINT8_MAX;
     2682                                Log12(("iemNativeEmitEndIf: Dropping hst reg %s for var #%u/%#x\n",
     2683                                       g_apszIemNativeHstRegNames[idxHstReg], idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar)));
     2684                            }
     2685                            continue;
     2686                        }
     2687                    }
     2688                    else if (!(pReNative->Core.bmVars & RT_BIT_32(idxVar)))
     2689                        continue;
     2690
     2691                    /* Irreconcilable, so drop it. */
     2692                    uint8_t const idxHstReg = pReNative->Core.aVars[idxVar].idxReg;
     2693                    if (idxHstReg != UINT8_MAX)
     2694                    {
     2695                        pReNative->Core.bmHstRegs &= ~RT_BIT_32(idxHstReg);
     2696                        pReNative->Core.aVars[idxVar].idxReg = UINT8_MAX;
     2697                        Log12(("iemNativeEmitEndIf: Dropping hst reg %s for var #%u/%#x (also dropped)\n",
     2698                               g_apszIemNativeHstRegNames[idxHstReg], idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar)));
     2699                    }
     2700                    Log11(("iemNativeEmitEndIf: Freeing variable #%u/%#x\n", idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar)));
     2701                    pReNative->Core.bmVars &= ~RT_BIT_32(idxVar);
     2702                } while (fVars);
     2703            }
     2704
     2705            /* Finally, check that the host register allocations matches. */
     2706            AssertMsgStmt(pReNative->Core.bmHstRegs == pOther->bmHstRegs,
     2707                          ("Core.bmHstRegs=%#x pOther->bmHstRegs=%#x - %#x\n",
     2708                           pReNative->Core.bmHstRegs, pOther->bmHstRegs, pReNative->Core.bmHstRegs ^ pOther->bmHstRegs),
     2709                          IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_COND_ENDIF_RECONCILIATION_FAILED));
    26062710        }
    2607         else
    2608         {
    2609             Assert(pReNative->Core.bmHstRegsWithGstShadow == 0);
    2610 #ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
    2611             Assert(pReNative->Core.bmGstRegShadowDirty == 0);
    2612 #endif
    2613         }
    2614 
    2615         /* Check variables next. For now we must require them to be identical
    2616            or stuff we can recreate. */
    2617         Assert(pReNative->Core.u64ArgVars == pOther->u64ArgVars);
    2618         uint32_t fVars = pReNative->Core.bmVars | pOther->bmVars;
    2619         if (fVars)
    2620         {
    2621             uint32_t const fVarsMustRemove = pReNative->Core.bmVars ^ pOther->bmVars;
    2622             do
    2623             {
    2624                 unsigned idxVar = ASMBitFirstSetU32(fVars) - 1;
    2625                 fVars &= ~RT_BIT_32(idxVar);
    2626 
    2627                 if (!(fVarsMustRemove & RT_BIT_32(idxVar)))
    2628                 {
    2629                     if (pReNative->Core.aVars[idxVar].idxReg == pOther->aVars[idxVar].idxReg)
    2630                         continue;
    2631                     if (pReNative->Core.aVars[idxVar].enmKind != kIemNativeVarKind_Stack)
    2632                     {
    2633                         uint8_t const idxHstReg = pReNative->Core.aVars[idxVar].idxReg;
    2634                         if (idxHstReg != UINT8_MAX)
    2635                         {
    2636                             pReNative->Core.bmHstRegs &= ~RT_BIT_32(idxHstReg);
    2637                             pReNative->Core.aVars[idxVar].idxReg = UINT8_MAX;
    2638                             Log12(("iemNativeEmitEndIf: Dropping hst reg %s for var #%u/%#x\n",
    2639                                    g_apszIemNativeHstRegNames[idxHstReg], idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar)));
    2640                         }
    2641                         continue;
    2642                     }
    2643                 }
    2644                 else if (!(pReNative->Core.bmVars & RT_BIT_32(idxVar)))
    2645                     continue;
    2646 
    2647                 /* Irreconcilable, so drop it. */
    2648                 uint8_t const idxHstReg = pReNative->Core.aVars[idxVar].idxReg;
    2649                 if (idxHstReg != UINT8_MAX)
    2650                 {
    2651                     pReNative->Core.bmHstRegs &= ~RT_BIT_32(idxHstReg);
    2652                     pReNative->Core.aVars[idxVar].idxReg = UINT8_MAX;
    2653                     Log12(("iemNativeEmitEndIf: Dropping hst reg %s for var #%u/%#x (also dropped)\n",
    2654                            g_apszIemNativeHstRegNames[idxHstReg], idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar)));
    2655                 }
    2656                 Log11(("iemNativeEmitEndIf: Freeing variable #%u/%#x\n", idxVar, IEMNATIVE_VAR_IDX_PACK(idxVar)));
    2657                 pReNative->Core.bmVars &= ~RT_BIT_32(idxVar);
    2658             } while (fVars);
    2659         }
    2660 
    2661         /* Finally, check that the host register allocations matches. */
    2662         AssertMsgStmt(pReNative->Core.bmHstRegs == pOther->bmHstRegs,
    2663                       ("Core.bmHstRegs=%#x pOther->bmHstRegs=%#x - %#x\n",
    2664                        pReNative->Core.bmHstRegs, pOther->bmHstRegs, pReNative->Core.bmHstRegs ^ pOther->bmHstRegs),
    2665                       IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_COND_ENDIF_RECONCILIATION_FAILED));
    26662711    }
    26672712
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette