Index: /trunk/src/VBox/VMM/MMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/MMInternal.h	(revision 7631)
+++ /trunk/src/VBox/VMM/MMInternal.h	(revision 7632)
@@ -145,4 +145,21 @@
 #if defined(VBOX_STRICT) || defined(__DOXYGEN__)
 # define MMHYPER_HEAP_FREE_POISON   0xCB
+#endif
+
+/** @def MMHYPER_HEAP_STRICT
+ * Enables a bunch of assertions in the heap code. */
+#if defined(VBOX_STRICT) || defined(__DOXYGEN__)
+# define MMHYPER_HEAP_STRICT 1
+# if 0 || defined(__DOXYGEN__)
+/** @def MMHYPER_HEAP_STRICT_FENCE
+ * Enables tail fence. */
+#  define MMHYPER_HEAP_STRICT_FENCE
+/** @def MMHYPER_HEAP_STRICT_FENCE_SIZE
+ * The fence size in bytes. */
+#  define MMHYPER_HEAP_STRICT_FENCE_SIZE    256
+/** @def MMHYPER_HEAP_STRICT_FENCE_U32
+ * The fence filler. */
+#  define MMHYPER_HEAP_STRICT_FENCE_U32     0xdeadbeef
+# endif
 #endif
 
Index: /trunk/src/VBox/VMM/VMMAll/MMAllHyper.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/MMAllHyper.cpp	(revision 7631)
+++ /trunk/src/VBox/VMM/VMMAll/MMAllHyper.cpp	(revision 7632)
@@ -37,8 +37,4 @@
 *   Defined Constants And Macros                                               *
 *******************************************************************************/
-#ifdef DEBUG
-# define MMHYPER_HEAP_STRICT 1
-#endif
-
 #define ASSERT_L(u1, u2)    AssertMsg((u1) <  (u2), ("u1=%#x u2=%#x\n", u1, u2))
 #define ASSERT_LE(u1, u2)   AssertMsg((u1) <= (u2), ("u1=%#x u2=%#x\n", u1, u2))
@@ -149,5 +145,5 @@
 static int mmHyperFree(PMMHYPERHEAP pHeap, PMMHYPERCHUNK pChunk);
 #ifdef MMHYPER_HEAP_STRICT
-static void mmR3HyperHeapCheck(PMMHYPERHEAP pHeap);
+static void mmHyperHeapCheck(PMMHYPERHEAP pHeap);
 #endif
 
@@ -299,5 +295,9 @@
     Log3(("mmHyperAllocChunk: Enter cb=%#x uAlignment=%#x\n", cb, uAlignment));
 #ifdef MMHYPER_HEAP_STRICT
-    mmR3HyperHeapCheck(pHeap);
+    mmHyperHeapCheck(pHeap);
+#endif
+#ifdef MMHYPER_HEAP_STRICT_FENCE
+    uint32_t cbFence = RT_MAX(MMHYPER_HEAP_STRICT_FENCE_SIZE, uAlignment);
+    cb += cbFence;
 #endif
 
@@ -509,6 +509,15 @@
     }
 
+#ifdef MMHYPER_HEAP_STRICT_FENCE
+    uint32_t *pu32End = (uint32_t *)((uint8_t *)(pRet + 1) + cb);
+    uint32_t *pu32EndReal = pRet->offNext
+                          ? (uint32_t *)((uint8_t *)pRet + pRet->offNext)
+                          : (uint32_t *)(pHeap->CTXSUFF(pbHeap) + pHeap->cbHeap);
+    cbFence += (uintptr_t)pu32EndReal - (uintptr_t)pu32End; Assert(!(cbFence & 0x3));
+    ASMMemFill32((uint8_t *)pu32EndReal - cbFence, cbFence, MMHYPER_HEAP_STRICT_FENCE_U32);
+    pu32EndReal[-1] = cbFence;
+#endif
 #ifdef MMHYPER_HEAP_STRICT
-    mmR3HyperHeapCheck(pHeap);
+    mmHyperHeapCheck(pHeap);
 #endif
     return pRet;
@@ -531,5 +540,5 @@
 
 #ifdef MMHYPER_HEAP_STRICT
-    mmR3HyperHeapCheck(pHeap);
+    mmHyperHeapCheck(pHeap);
 #endif
 
@@ -615,5 +624,5 @@
 
 #ifdef MMHYPER_HEAP_STRICT
-    mmR3HyperHeapCheck(pHeap);
+    mmHyperHeapCheck(pHeap);
 #endif
     return pvRet;
@@ -776,4 +785,8 @@
                     VERR_INVALID_POINTER);
 
+#ifdef MMHYPER_HEAP_STRICT
+    mmHyperHeapCheck(pHeap);
+#endif
+
 #if defined(VBOX_WITH_STATISTICS) || defined(MMHYPER_HEAP_FREE_POISON)
     /* calc block size. */
@@ -857,8 +870,4 @@
     Log3(("mmHyperFree: Enter pHeap=%p pChunk=%p\n", pHeap, pChunk));
     PMMHYPERCHUNKFREE   pFree = (PMMHYPERCHUNKFREE)pChunk;
-
-#ifdef MMHYPER_HEAP_STRICT
-    mmR3HyperHeapCheck(pHeap);
-#endif
 
     /*
@@ -1009,5 +1018,5 @@
 
 #ifdef MMHYPER_HEAP_STRICT
-    mmR3HyperHeapCheck(pHeap);
+    mmHyperHeapCheck(pHeap);
 #endif
     return VINF_SUCCESS;
@@ -1015,9 +1024,49 @@
 
 
+#if defined(DEBUG) || defined(MMHYPER_HEAP_STRICT)
+/**
+ * Dumps a heap chunk to the log.
+ *
+ * @param   pHeap       Pointer to the heap.
+ * @param   pCur        Pointer to the chunk.
+ */
+static void mmHyperHeapDumpOne(PMMHYPERHEAP pHeap, PMMHYPERCHUNKFREE pCur)
+{
+    if (MMHYPERCHUNK_ISUSED(&pCur->core))
+    {
+        if (pCur->core.offStat)
+        {
+            PMMHYPERSTAT pStat = (PMMHYPERSTAT)((uintptr_t)pCur + pCur->core.offStat);
+            const char *pszSelf = pCur->core.offStat == sizeof(MMHYPERCHUNK) ? " stat record" : "";
+#ifdef IN_RING3
+            Log(("%p  %06x USED offNext=%06x offPrev=-%06x %s%s\n",
+                 pCur, (uintptr_t)pCur - (uintptr_t)CTXSUFF(pHeap->pbHeap),
+                 pCur->core.offNext, -MMHYPERCHUNK_GET_OFFPREV(&pCur->core),
+                 mmR3GetTagName((MMTAG)pStat->Core.Key), pszSelf));
+#else
+            Log(("%p  %06x USED offNext=%06x offPrev=-%06x %d%s\n",
+                 pCur, (uintptr_t)pCur - (uintptr_t)CTXSUFF(pHeap->pbHeap),
+                 pCur->core.offNext, -MMHYPERCHUNK_GET_OFFPREV(&pCur->core),
+                 (MMTAG)pStat->Core.Key, pszSelf));
+#endif
+        }
+        else
+            Log(("%p  %06x USED offNext=%06x offPrev=-%06x\n",
+                 pCur, (uintptr_t)pCur - (uintptr_t)CTXSUFF(pHeap->pbHeap),
+                 pCur->core.offNext, -MMHYPERCHUNK_GET_OFFPREV(&pCur->core)));
+    }
+    else
+        Log(("%p  %06x FREE offNext=%06x offPrev=-%06x : cb=%06x offNext=%06x offPrev=-%06x\n",
+             pCur, (uintptr_t)pCur - (uintptr_t)CTXSUFF(pHeap->pbHeap),
+             pCur->core.offNext, -MMHYPERCHUNK_GET_OFFPREV(&pCur->core), pCur->cb, pCur->offNext, pCur->offPrev));
+}
+#endif /* DEBUG || MMHYPER_HEAP_STRICT */
+
+
 #ifdef MMHYPER_HEAP_STRICT
 /**
  * Internal consitency check.
  */
-static void mmR3HyperHeapCheck(PMMHYPERHEAP pHeap)
+static void mmHyperHeapCheck(PMMHYPERHEAP pHeap)
 {
     PMMHYPERCHUNKFREE pPrev = NULL;
@@ -1033,4 +1082,31 @@
                       ("pPrev->core.offNext=%d offPrev=%d\n", pPrev->core.offNext, MMHYPERCHUNK_GET_OFFPREV(&pCur->core)));
 
+# ifdef MMHYPER_HEAP_STRICT_FENCE
+        uint32_t off = (uint8_t *)pCur - CTXSUFF(pHeap->pbHeap);
+        if (    MMHYPERCHUNK_ISUSED(&pCur->core)
+            &&  off < pHeap->offPageAligned)
+        {
+            uint32_t cbCur = pCur->core.offNext
+                           ? pCur->core.offNext
+                           : pHeap->cbHeap - off;
+            uint32_t *pu32End = ((uint32_t *)((uint8_t *)pCur + cbCur));
+            uint32_t cbFence = pu32End[-1];
+            if (RT_UNLIKELY(    cbFence >= cbCur - sizeof(*pCur)
+                            ||  cbFence < MMHYPER_HEAP_STRICT_FENCE_SIZE))
+            {
+                mmHyperHeapDumpOne(pHeap, pCur);
+                Assert(cbFence < cbCur - sizeof(*pCur));
+                Assert(cbFence >= MMHYPER_HEAP_STRICT_FENCE_SIZE);
+            }
+
+            uint32_t *pu32Bad = ASMMemIsAllU32((uint8_t *)pu32End - cbFence, cbFence - sizeof(uint32_t), MMHYPER_HEAP_STRICT_FENCE_U32);
+            if (RT_UNLIKELY(pu32Bad))
+            {
+                mmHyperHeapDumpOne(pHeap, pCur);
+                Assert(!pu32Bad);
+            }
+        }
+# endif
+
         /* next */
         if (!pCur->core.offNext)
@@ -1043,4 +1119,18 @@
 
 
+/**
+ * Performs consistency checks on the heap if MMHYPER_HEAP_STRICT was
+ * defined at build time.
+ *
+ * @param   pVM         Pointer to the shared VM structure.
+ */
+MMDECL(void) MMHyperHeapCheck(PVM pVM)
+{
+#ifdef MMHYPER_HEAP_STRICT
+    mmHyperHeapCheck(CTXSUFF(pVM->mm.s.pHyperHeap));
+#endif
+}
+
+
 #ifdef DEBUG
 /**
@@ -1055,31 +1145,5 @@
     for (;;)
     {
-        if (MMHYPERCHUNK_ISUSED(&pCur->core))
-        {
-            if (pCur->core.offStat)
-            {
-                PMMHYPERSTAT pStat = (PMMHYPERSTAT)((uintptr_t)pCur + pCur->core.offStat);
-                const char *pszSelf = pCur->core.offStat == sizeof(MMHYPERCHUNK) ? " stat record" : "";
-#ifdef IN_RING3
-                Log(("%p  %06x USED offNext=%06x offPrev=-%06x %s%s\n",
-                     pCur, (uintptr_t)pCur - (uintptr_t)CTXSUFF(pHeap->pbHeap),
-                     pCur->core.offNext, -MMHYPERCHUNK_GET_OFFPREV(&pCur->core),
-                     mmR3GetTagName((MMTAG)pStat->Core.Key), pszSelf));
-#else
-                Log(("%p  %06x USED offNext=%06x offPrev=-%06x %d%s\n",
-                     pCur, (uintptr_t)pCur - (uintptr_t)CTXSUFF(pHeap->pbHeap),
-                     pCur->core.offNext, -MMHYPERCHUNK_GET_OFFPREV(&pCur->core),
-                     (MMTAG)pStat->Core.Key, pszSelf));
-#endif
-            }
-            else
-                Log(("%p  %06x USED offNext=%06x offPrev=-%06x\n",
-                     pCur, (uintptr_t)pCur - (uintptr_t)CTXSUFF(pHeap->pbHeap),
-                     pCur->core.offNext, -MMHYPERCHUNK_GET_OFFPREV(&pCur->core)));
-        }
-        else
-            Log(("%p  %06x FREE offNext=%06x offPrev=-%06x : cb=%06x offNext=%06x offPrev=-%06x\n",
-                 pCur, (uintptr_t)pCur - (uintptr_t)CTXSUFF(pHeap->pbHeap),
-                 pCur->core.offNext, -MMHYPERCHUNK_GET_OFFPREV(&pCur->core), pCur->cb, pCur->offNext, pCur->offPrev));
+        mmHyperHeapDumpOne(pHeap, pCur);
 
         /* next */
