Index: /trunk/src/VBox/VMM/VMMAll/IEMAllN8veExecMem.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllN8veExecMem.cpp	(revision 106328)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllN8veExecMem.cpp	(revision 106329)
@@ -367,5 +367,9 @@
      * Before we can start, we must process delayed frees.
      */
+#if 1
+    PIEMTBALLOCATOR const pTbAllocator = iemTbAllocatorFreeBulkStart(pVCpu);
+#else
     iemTbAllocatorProcessDelayedFrees(pVCpu, pVCpu->iem.s.pTbAllocatorR3);
+#endif
 
     AssertCompile(RT_IS_POWER_OF_TWO(IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SIZE));
@@ -455,5 +459,9 @@
             cbPruned += cbBlock;
 
+#if 1
+            iemTbAllocatorFreeBulk(pVCpu, pTbAllocator, pTb);
+#else
             iemTbAllocatorFree(pVCpu, pTb);
+#endif
         }
         else
@@ -461,4 +469,6 @@
     }
     STAM_REL_PROFILE_ADD_PERIOD(&pExecMemAllocator->StatPruneRecovered, cbPruned);
+
+    pVCpu->iem.s.ppTbLookupEntryR3 = &pVCpu->iem.s.pTbLookupEntryDummyR3;
 
     /*
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp	(revision 106328)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp	(revision 106329)
@@ -912,8 +912,17 @@
 /**
  * Inner free worker.
- */
-static void iemTbAllocatorFreeInner(PVMCPUCC pVCpu, PIEMTBALLOCATOR pTbAllocator,
-                                    PIEMTB pTb, uint32_t idxChunk, uint32_t idxInChunk)
-{
+ *
+ * The @a a_fType parameter allows us to eliminate the type check when we know
+ * which type of TB is being freed.
+ */
+template<uint32_t a_fType>
+DECL_FORCE_INLINE(void)
+iemTbAllocatorFreeInner(PVMCPUCC pVCpu, PIEMTBALLOCATOR pTbAllocator, PIEMTB pTb, uint32_t idxChunk, uint32_t idxInChunk)
+{
+#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
+    AssertCompile(a_fType == 0 || a_fType == IEMTB_F_TYPE_THREADED || a_fType == IEMTB_F_TYPE_NATIVE);
+#else
+    AssertCompile(a_fType == 0 || a_fType == IEMTB_F_TYPE_THREADED);
+#endif
     Assert(idxChunk < pTbAllocator->cAllocatedChunks); RT_NOREF(idxChunk);
     Assert(idxInChunk < pTbAllocator->cTbsPerChunk); RT_NOREF(idxInChunk);
@@ -932,20 +941,37 @@
      * Free the TB itself.
      */
-    switch (pTb->fFlags & IEMTB_F_TYPE_MASK)
-    {
-        case IEMTB_F_TYPE_THREADED:
-            pTbAllocator->cThreadedTbs -= 1;
-            RTMemFree(pTb->Thrd.paCalls);
-            break;
+    if RT_CONSTEXPR_IF(a_fType == 0)
+        switch (pTb->fFlags & IEMTB_F_TYPE_MASK)
+        {
+            case IEMTB_F_TYPE_THREADED:
+                pTbAllocator->cThreadedTbs -= 1;
+                RTMemFree(pTb->Thrd.paCalls);
+                break;
 #ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
-        case IEMTB_F_TYPE_NATIVE:
-            pTbAllocator->cNativeTbs -= 1;
-            iemExecMemAllocatorFree(pVCpu, pTb->Native.paInstructions,
-                                    pTb->Native.cInstructions * sizeof(pTb->Native.paInstructions[0]));
-            pTb->Native.paInstructions = NULL; /* required by iemExecMemAllocatorPrune */
-            break;
-#endif
-        default:
-            AssertFailed();
+            case IEMTB_F_TYPE_NATIVE:
+                pTbAllocator->cNativeTbs -= 1;
+                iemExecMemAllocatorFree(pVCpu, pTb->Native.paInstructions,
+                                        pTb->Native.cInstructions * sizeof(pTb->Native.paInstructions[0]));
+                pTb->Native.paInstructions = NULL; /* required by iemExecMemAllocatorPrune */
+                break;
+#endif
+            default:
+                AssertFailed();
+        }
+#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
+    else if RT_CONSTEXPR_IF(a_fType == IEMTB_F_TYPE_NATIVE)
+    {
+        Assert((pTb->fFlags & IEMTB_F_TYPE_MASK) == IEMTB_F_TYPE_NATIVE);
+        pTbAllocator->cNativeTbs -= 1;
+        iemExecMemAllocatorFree(pVCpu, pTb->Native.paInstructions,
+                                pTb->Native.cInstructions * sizeof(pTb->Native.paInstructions[0]));
+        pTb->Native.paInstructions = NULL; /* required by iemExecMemAllocatorPrune */
+    }
+#endif
+    else
+    {
+        Assert((pTb->fFlags & IEMTB_F_TYPE_MASK) == IEMTB_F_TYPE_THREADED);
+        pTbAllocator->cThreadedTbs -= 1;
+        RTMemFree(pTb->Thrd.paCalls);
     }
 
@@ -993,7 +1019,42 @@
      */
     pVCpu->iem.s.ppTbLookupEntryR3 = &pVCpu->iem.s.pTbLookupEntryDummyR3;
-    iemTbAllocatorFreeInner(pVCpu, pTbAllocator, pTb, idxChunk, (uint32_t)idxInChunk);
-}
-
+    iemTbAllocatorFreeInner<0>(pVCpu, pTbAllocator, pTb, idxChunk, (uint32_t)idxInChunk);
+}
+
+#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
+
+/**
+ * Interface used by iemExecMemAllocatorPrune.
+ */
+DECLHIDDEN(void) iemTbAllocatorFreeBulk(PVMCPUCC pVCpu, PIEMTBALLOCATOR pTbAllocator, PIEMTB pTb)
+{
+    Assert(pTbAllocator->uMagic == IEMTBALLOCATOR_MAGIC);
+
+    uint8_t const idxChunk = pTb->idxAllocChunk;
+    AssertLogRelReturnVoid(idxChunk < pTbAllocator->cAllocatedChunks);
+    uintptr_t const idxInChunk = pTb - pTbAllocator->aChunks[idxChunk].paTbs;
+    AssertLogRelReturnVoid(idxInChunk < pTbAllocator->cTbsPerChunk);
+
+    iemTbAllocatorFreeInner<IEMTB_F_TYPE_NATIVE>(pVCpu, pTbAllocator, pTb, idxChunk, (uint32_t)idxInChunk);
+}
+
+
+/**
+ * Interface used by iemExecMemAllocatorPrune.
+ */
+DECLHIDDEN(PIEMTBALLOCATOR) iemTbAllocatorFreeBulkStart(PVMCPUCC pVCpu)
+{
+    PIEMTBALLOCATOR const pTbAllocator = pVCpu->iem.s.pTbAllocatorR3;
+    Assert(pTbAllocator && pTbAllocator->uMagic == IEMTBALLOCATOR_MAGIC);
+
+    iemTbAllocatorProcessDelayedFrees(pVCpu, pTbAllocator);
+
+    /* It should be sufficient to do this once. */
+    pVCpu->iem.s.ppTbLookupEntryR3 = &pVCpu->iem.s.pTbLookupEntryDummyR3;
+
+    return pTbAllocator;
+}
+
+#endif /* VBOX_WITH_IEM_NATIVE_RECOMPILER */
 
 /**
@@ -1083,5 +1144,5 @@
             PIEMTB const pTb = &paTbs[idxTb];
             if (pTb->fFlags)
-                iemTbAllocatorFreeInner(pVCpu, pTbAllocator, pTb, idxChunk, idxTb);
+                iemTbAllocatorFreeInner<0>(pVCpu, pTbAllocator, pTb, idxChunk, idxTb);
         }
     }
@@ -1247,5 +1308,5 @@
 
         /* Free the TB. */
-        iemTbAllocatorFreeInner(pVCpu, pTbAllocator, pTb, idxChunk, idxInChunk);
+        iemTbAllocatorFreeInner<0>(pVCpu, pTbAllocator, pTb, idxChunk, idxInChunk);
         cFreedTbs++; /* paranoia */
     }
@@ -1370,5 +1431,5 @@
         {
             cMaxInstrs = RT_MAX(cMaxInstrs, pTb->Native.cInstructions);
-            iemTbAllocatorFreeInner(pVCpu, pTbAllocator, pTb, idxChunk, idxInChunk);
+            iemTbAllocatorFreeInner<IEMTB_F_TYPE_NATIVE>(pVCpu, pTbAllocator, pTb, idxChunk, idxInChunk);
             cFreedTbs++;
             if (cFreedTbs >= 8 && cMaxInstrs >= cNeededInstrs)
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 106328)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 106329)
@@ -6704,4 +6704,6 @@
 void                iemTbAllocatorProcessDelayedFrees(PVMCPUCC pVCpu, PIEMTBALLOCATOR pTbAllocator);
 void                iemTbAllocatorFreeupNativeSpace(PVMCPUCC pVCpu, uint32_t cNeededInstrs);
+DECLHIDDEN(PIEMTBALLOCATOR) iemTbAllocatorFreeBulkStart(PVMCPUCC pVCpu);
+DECLHIDDEN(void)    iemTbAllocatorFreeBulk(PVMCPUCC pVCpu, PIEMTBALLOCATOR pTbAllocator, PIEMTB pTb);
 DECLHIDDEN(const char *) iemTbFlagsToString(uint32_t fFlags, char *pszBuf, size_t cbBuf) RT_NOEXCEPT;
 DECLHIDDEN(void)    iemThreadedDisassembleTb(PCIEMTB pTb, PCDBGFINFOHLP pHlp) RT_NOEXCEPT;
