- Timestamp:
- Mar 28, 2024 9:50:41 PM (10 months ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
r104101 r104108 159 159 /** The chunk sub-allocation unit size as a shift factor. */ 160 160 #define IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SHIFT 7 161 /** Enables adding a header to the sub-allocator allocations. 162 * This is useful for freeing up executable memory among other things. */ 163 #define IEMEXECMEM_ALT_SUB_WITH_ALLOC_HEADER 164 161 165 162 166 #if defined(IN_RING3) && !defined(RT_OS_WINDOWS) … … 344 348 * portion corresponding to an chunk). */ 345 349 uint32_t cBitmapElementsPerChunk; 350 # ifdef VBOX_WITH_STATISTICS 351 STAMPROFILE StatAlloc; 352 # endif 346 353 #else 347 354 /** @name Tweaks to get 64 byte aligned allocats w/o unnecessary fragmentation. … … 378 385 379 386 387 #ifdef IEMEXECMEM_ALT_SUB_WITH_ALLOC_HEADER 388 /** 389 * Allocation header. 390 */ 391 typedef struct IEMEXECMEMALLOCHDR 392 { 393 /** Magic value / eyecatcher (IEMEXECMEMALLOCHDR_MAGIC). */ 394 uint32_t uMagic; 395 /** The allocation chunk (for speeding up freeing). */ 396 uint32_t idxChunk; 397 /** Pointer to the translation block the allocation belongs to. 398 * This is the whole point of the header. */ 399 PIEMTB pTb; 400 } IEMEXECMEMALLOCHDR; 401 /** Pointer to an allocation header. */ 402 typedef IEMEXECMEMALLOCHDR *PIEMEXECMEMALLOCHDR; 403 /** Magic value for IEMEXECMEMALLOCHDR ('ExeM'). */ 404 # define IEMEXECMEMALLOCHDR_MAGIC UINT32_C(0x4d657845) 405 #endif 406 407 380 408 static int iemExecMemAllocatorGrow(PVMCPUCC pVCpu, PIEMEXECMEMALLOCATOR pExecMemAllocator); 381 409 … … 385 413 * the heap statistics. 386 414 */ 387 static void * 388 415 static void *iemExecMemAllocatorAllocTailCode(PIEMEXECMEMALLOCATOR pExecMemAllocator, void *pvRet, 416 uint32_t cbReq, uint32_t idxChunk) 389 417 { 390 418 pExecMemAllocator->cAllocations += 1; … … 419 447 #ifdef IEMEXECMEM_USE_ALT_SUB_ALLOCATOR 420 448 static void *iemExecMemAllocatorAllocInChunkInt(PIEMEXECMEMALLOCATOR pExecMemAllocator, uint64_t *pbmAlloc, uint32_t idxFirst, 421 uint32_t cToScan, uint32_t cReqUnits, uint32_t idxChunk )449 uint32_t cToScan, uint32_t cReqUnits, uint32_t idxChunk, PIEMTB pTb) 422 450 { 423 451 /* … … 447 475 pChunk->idxFreeHint = (uint32_t)iBit + cReqUnits; 448 476 477 # ifdef IEMEXECMEM_ALT_SUB_WITH_ALLOC_HEADER 478 PIEMEXECMEMALLOCHDR pHdr = (PIEMEXECMEMALLOCHDR)((uint8_t *)pChunk->pvChunk 479 + ( (idxFirst + (uint32_t)iBit) 480 << IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SHIFT)); 481 pHdr->uMagic = IEMEXECMEMALLOCHDR_MAGIC; 482 pHdr->idxChunk = idxChunk; 483 pHdr->pTb = pTb; 484 return iemExecMemAllocatorAllocTailCode(pExecMemAllocator, pHdr + 1, 485 cReqUnits << IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SHIFT, idxChunk); 486 #else 487 RT_NOREF(pTb); 449 488 void * const pvRet = (uint8_t *)pChunk->pvChunk 450 489 + ((idxFirst + (uint32_t)iBit) << IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SHIFT); 451 452 490 return iemExecMemAllocatorAllocTailCode(pExecMemAllocator, pvRet, 453 491 cReqUnits << IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SHIFT, idxChunk); 492 #endif 454 493 } 455 494 … … 461 500 462 501 463 static void *iemExecMemAllocatorAllocInChunk(PIEMEXECMEMALLOCATOR pExecMemAllocator, uint32_t idxChunk, uint32_t cbReq) 502 static void * 503 iemExecMemAllocatorAllocInChunk(PIEMEXECMEMALLOCATOR pExecMemAllocator, uint32_t idxChunk, uint32_t cbReq, PIEMTB pTb) 464 504 { 465 505 #ifdef IEMEXECMEM_USE_ALT_SUB_ALLOCATOR … … 467 507 * Figure out how much to allocate. 468 508 */ 469 uint32_t const cReqUnits = (cbReq + IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SIZE - 1) >> IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SHIFT; 509 # ifdef IEMEXECMEM_ALT_SUB_WITH_ALLOC_HEADER 510 uint32_t const cReqUnits = (cbReq + sizeof(IEMEXECMEMALLOCHDR) + IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SIZE - 1) 511 # else 512 uint32_t const cReqUnits = (cbReq + IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SIZE - 1) 513 # endif 514 >> IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SHIFT; 470 515 if (cReqUnits <= pExecMemAllocator->aChunks[idxChunk].cFreeUnits) 471 516 { … … 475 520 { 476 521 void *pvRet = iemExecMemAllocatorAllocInChunkInt(pExecMemAllocator, pbmAlloc, idxHint, 477 pExecMemAllocator->cUnitsPerChunk - idxHint, cReqUnits, idxChunk); 522 pExecMemAllocator->cUnitsPerChunk - idxHint, 523 cReqUnits, idxChunk, pTb); 478 524 if (pvRet) 479 525 return pvRet; … … 481 527 return iemExecMemAllocatorAllocInChunkInt(pExecMemAllocator, pbmAlloc, 0, 482 528 RT_MIN(pExecMemAllocator->cUnitsPerChunk, RT_ALIGN_32(idxHint + cReqUnits, 64)), 483 cReqUnits, idxChunk );529 cReqUnits, idxChunk, pTb); 484 530 } 485 531 #else … … 487 533 if (pvRet) 488 534 return iemExecMemAllocatorAllocTailCode(pExecMemAllocator, pvRet, cbReq, idxChunk); 535 RT_NOREF(pTb); 489 536 #endif 490 537 return NULL; … … 501 548 * thread. 502 549 * @param cbReq How many bytes are required. 503 */ 504 static void *iemExecMemAllocatorAlloc(PVMCPU pVCpu, uint32_t cbReq) 550 * @param pTb The translation block that will be using the allocation. 551 */ 552 static void *iemExecMemAllocatorAlloc(PVMCPU pVCpu, uint32_t cbReq, PIEMTB pTb) 505 553 { 506 554 PIEMEXECMEMALLOCATOR pExecMemAllocator = pVCpu->iem.s.pExecMemAllocatorR3; 507 555 AssertReturn(pExecMemAllocator && pExecMemAllocator->uMagic == IEMEXECMEMALLOCATOR_MAGIC, NULL); 508 556 AssertMsgReturn(cbReq > 32 && cbReq < _512K, ("%#x\n", cbReq), NULL); 557 STAM_PROFILE_START(&pExecMemAllocator->StatAlloc, a); 509 558 510 559 /* … … 531 580 for (uint32_t idxChunk = idxChunkHint; idxChunk < cChunks; idxChunk++) 532 581 { 533 void *pvRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq );582 void *pvRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, pTb); 534 583 if (pvRet) 584 { 585 STAM_PROFILE_STOP(&pExecMemAllocator->StatAlloc, a); 535 586 return pvRet; 587 } 536 588 } 537 589 for (uint32_t idxChunk = 0; idxChunk < idxChunkHint; idxChunk++) 538 590 { 539 void *pvRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq );591 void *pvRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, pTb); 540 592 if (pvRet) 593 { 594 STAM_PROFILE_STOP(&pExecMemAllocator->StatAlloc, a); 541 595 return pvRet; 596 } 542 597 } 543 598 } … … 552 607 553 608 uint32_t const idxChunk = pExecMemAllocator->cChunks - 1; 554 void *pvRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq );609 void *pvRet = iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbReq, pTb); 555 610 if (pvRet) 611 { 612 STAM_PROFILE_STOP(&pExecMemAllocator->StatAlloc, a); 556 613 return pvRet; 614 } 557 615 AssertFailed(); 558 616 } … … 566 624 { 567 625 STAM_REL_COUNTER_INC(&pVCpu->iem.s.StatNativeExecMemInstrBufAllocFailed); 626 STAM_PROFILE_STOP(&pExecMemAllocator->StatAlloc, a); 568 627 return NULL; 569 628 } 570 629 } 571 572 630 } 573 631 … … 601 659 PIEMEXECMEMALLOCATOR pExecMemAllocator = pVCpu->iem.s.pExecMemAllocatorR3; 602 660 Assert(pExecMemAllocator && pExecMemAllocator->uMagic == IEMEXECMEMALLOCATOR_MAGIC); 603 Assert(pv); 604 #ifdef IEMEXECMEM_USE_ALT_SUB_ALLOCATOR 661 AssertPtr(pv); 662 #ifndef IEMEXECMEM_USE_ALT_SUB_ALLOCATOR 663 Assert(!((uintptr_t)pv & 63)); 664 #else 665 # ifndef IEMEXECMEM_ALT_SUB_WITH_ALLOC_HEADER 605 666 Assert(!((uintptr_t)pv & (IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SIZE - 1))); 606 #else 607 Assert(!((uintptr_t)pv & 63)); 667 # else 668 PIEMEXECMEMALLOCHDR pHdr = (PIEMEXECMEMALLOCHDR)pv - 1; 669 Assert(!((uintptr_t)pHdr & (IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SIZE - 1))); 670 AssertReturnVoid(pHdr->uMagic == IEMEXECMEMALLOCHDR_MAGIC); 671 uint32_t const idxChunk = pHdr->idxChunk; 672 AssertReturnVoid(idxChunk < pExecMemAllocator->cChunks); 673 pv = pHdr; 674 # endif 608 675 #endif 609 676 … … 617 684 /* Free it / assert sanity. */ 618 685 #if defined(VBOX_STRICT) || defined(IEMEXECMEM_USE_ALT_SUB_ALLOCATOR) 686 bool fFound = false; 687 uint32_t const cbChunk = pExecMemAllocator->cbChunk; 688 # ifndef IEMEXECMEM_ALT_SUB_WITH_ALLOC_HEADER 619 689 uint32_t const cChunks = pExecMemAllocator->cChunks; 620 uint32_t const cbChunk = pExecMemAllocator->cbChunk;621 bool fFound = false;622 690 for (uint32_t idxChunk = 0; idxChunk < cChunks; idxChunk++) 691 # endif 623 692 { 624 693 uintptr_t const offChunk = (uintptr_t)pv - (uintptr_t)pExecMemAllocator->aChunks[idxChunk].pvChunk; … … 636 705 AssertReturnVoid(ASMBitTest(pbmAlloc, idxFirst + i)); 637 706 ASMBitClearRange(pbmAlloc, idxFirst, idxFirst + cReqUnits); 638 707 # ifdef IEMEXECMEM_ALT_SUB_WITH_ALLOC_HEADER 708 pHdr->uMagic = 0; 709 pHdr->idxChunk = 0; 710 pHdr->pTb = NULL; 711 # endif 639 712 pExecMemAllocator->aChunks[idxChunk].cFreeUnits += cReqUnits; 640 713 pExecMemAllocator->aChunks[idxChunk].idxFreeHint = idxFirst; … … 738 811 unsigned const cbNeededAligned = RT_ALIGN_32(cbNeeded, IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SIZE); 739 812 PIMAGE_RUNTIME_FUNCTION_ENTRY const paFunctions 740 = (PIMAGE_RUNTIME_FUNCTION_ENTRY)iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbNeededAligned );813 = (PIMAGE_RUNTIME_FUNCTION_ENTRY)iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbNeededAligned, NULL); 741 814 # else 742 815 unsigned const cbNeededAligned = RT_ALIGN_32(cbNeeded + pExecMemAllocator->cbHeapBlockHdr, 64) … … 982 1055 # ifdef IEMEXECMEM_USE_ALT_SUB_ALLOCATOR 983 1056 unsigned const cbNeededAligned = RT_ALIGN_32(cbNeeded, IEMEXECMEM_ALT_SUB_ALLOC_UNIT_SIZE); 984 GDBJITSYMFILE * const pSymFile = (GDBJITSYMFILE *)iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, cbNeededAligned); 1057 GDBJITSYMFILE * const pSymFile = (GDBJITSYMFILE *)iemExecMemAllocatorAllocInChunk(pExecMemAllocator, idxChunk, 1058 cbNeededAligned, NULL); 985 1059 # else 986 1060 unsigned const cbNeededAligned = RT_ALIGN_32(cbNeeded + pExecMemAllocator->cbHeapBlockHdr, 64) … … 1559 1633 1560 1634 pExecMemAllocator->idxChunkHint = 0; 1635 1636 /* 1637 * Register statistics. 1638 */ 1639 PUVM const pUVM = pVCpu->pUVCpu->pUVM; 1640 STAMR3RegisterFU(pUVM, &pExecMemAllocator->cAllocations, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, 1641 "Current number of allocations", "/IEM/CPU%u/re/ExecMem/cAllocations", pVCpu->idCpu); 1642 STAMR3RegisterFU(pUVM, &pExecMemAllocator->cChunks, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 1643 "Currently allocated chunks", "/IEM/CPU%u/re/ExecMem/cChunks", pVCpu->idCpu); 1644 STAMR3RegisterFU(pUVM, &pExecMemAllocator->cMaxChunks, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 1645 "Maximum number of chunks", "/IEM/CPU%u/re/ExecMem/cMaxChunks", pVCpu->idCpu); 1646 STAMR3RegisterFU(pUVM, &pExecMemAllocator->cbChunk, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, 1647 "Allocation chunk size", "/IEM/CPU%u/re/ExecMem/cbChunk", pVCpu->idCpu); 1648 STAMR3RegisterFU(pUVM, &pExecMemAllocator->cbAllocated, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, 1649 "Number of bytes current allocated", "/IEM/CPU%u/re/ExecMem/cbAllocated", pVCpu->idCpu); 1650 STAMR3RegisterFU(pUVM, &pExecMemAllocator->cbFree, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, 1651 "Number of bytes current free", "/IEM/CPU%u/re/ExecMem/cbFree", pVCpu->idCpu); 1652 STAMR3RegisterFU(pUVM, &pExecMemAllocator->cbTotal, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, 1653 "Total number of byte", "/IEM/CPU%u/re/ExecMem/cbTotal", pVCpu->idCpu); 1654 #ifdef VBOX_WITH_STATISTICS 1655 STAMR3RegisterFU(pUVM, &pExecMemAllocator->StatAlloc, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, 1656 "Profiling the allocator", "/IEM/CPU%u/re/ExecMem/ProfAlloc", pVCpu->idCpu); 1657 #endif 1561 1658 1562 1659 return VINF_SUCCESS; … … 10703 10800 iemTbAllocatorProcessDelayedFrees(pVCpu, pVCpu->iem.s.pTbAllocatorR3); 10704 10801 10705 PIEMNATIVEINSTR const paFinalInstrBuf = (PIEMNATIVEINSTR)iemExecMemAllocatorAlloc(pVCpu, off * sizeof(IEMNATIVEINSTR) );10802 PIEMNATIVEINSTR const paFinalInstrBuf = (PIEMNATIVEINSTR)iemExecMemAllocatorAlloc(pVCpu, off * sizeof(IEMNATIVEINSTR), pTb); 10706 10803 AssertReturn(paFinalInstrBuf, pTb); 10707 10804 memcpy(paFinalInstrBuf, pReNative->pInstrBuf, off * sizeof(paFinalInstrBuf[0])); -
trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
r104095 r104108 396 396 # endif 397 397 STAMR3RegisterF(pVM, (void *)&pTbAllocator->StatPruneNative, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, 398 "Time spent freeing up native TBs when out of executable memory", "/IEM/CPU%u/re/ TbPruningNative", idCpu);398 "Time spent freeing up native TBs when out of executable memory", "/IEM/CPU%u/re/ExecMem/TbPruningNative", idCpu); 399 399 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cAllocatedChunks, STAMTYPE_U16, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 400 400 "Populated TB chunks", "/IEM/CPU%u/re/cTbChunks", idCpu);
Note:
See TracChangeset
for help on using the changeset viewer.