home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Memory / MemoryHe.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  34.2 KB  |  1,194 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MemoryHe.cpp
  3.  
  4.     Contains:    MemoryHeap class implementation
  5.  
  6.     Owned by:    Michael Burbidge, Jens Alfke
  7.     Owned by:    Jens Alfke
  8.  
  9.     Copyright:    © 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.     
  13.         <16>    10/24/95    jpa        1293441: Added slush-fund.
  14.         <15>      8/4/95    DM        Leak detection [1267956]
  15.         <14>      6/7/95    jpa        IsValidBlock calls hooks to check for
  16.                                     prefix/suffix validity. [1256829]
  17.         <13>      5/5/95    TJ        jpa: Don't call hooks in nondebug build.
  18.         <12>      5/4/95    jpa        Support for finding largest free block
  19.                                     [1235657] and validating memory ranges
  20.                                     [1246077]
  21.         <11>    12/20/94    jpa        Fixed constructor typo that turned on
  22.                                     fZapOnFree.
  23.         <10>     12/5/94    jpa        Nuked errant pragma lib_export's. [1195676]
  24.          <9>    10/24/94    jpa        Constness [1194286].
  25.          <8>     9/29/94    RA        1189812: Mods for 68K build.
  26.          <7>     9/14/94    jpa        Eliminated dependencies on rest of OpenDoc.
  27.                                     Added support for getting the heap of a
  28.                                     block. [1186692]
  29.          <6>     8/17/94    jpa        Added support for walking heaps [1179567].
  30.          <5>      8/8/94    jpa        Zap old block after reallocate.
  31.          <4>      8/2/94    jpa        Fixed bug in BlockSize (wasn't calling
  32.                                     hooks when it should)
  33.          <3>     6/18/94    MB        More initial SOM deployment
  34.          <2>     6/10/94    MB        Make it build
  35.          <1>      6/9/94    MB        first checked in
  36.          <3>     5/26/94    MB        #1162181: Fixed MMM integration bug
  37.          <2>      5/9/94    MB        #1162181: Changes necessary to install MMM.
  38.          <1>     4/29/94    MB        first checked in
  39.     To Do:
  40.     In Progress:
  41.         
  42. */
  43.  
  44. #ifndef _PLATFMEM_
  45. #include "PlatfMem.h"
  46. #endif
  47.  
  48. #ifndef _MEMORYHE_
  49. #include "MemoryHe.h"
  50. #endif
  51.  
  52. #ifndef _MEMHOOKS_
  53. #include "MemHooks.h"
  54. #endif
  55.  
  56. #ifndef __MEMORY__
  57. #include <Memory.h>
  58. #endif
  59.  
  60. #ifndef __STDIO__
  61. #include <stdio.h>
  62. #endif
  63.  
  64.  
  65. //========================================================================================
  66. // CLASS ODMemoryHook (MM_DEBUG only)
  67. //========================================================================================
  68.  
  69. #if MM_DEBUG
  70. //----------------------------------------------------------------------------------------
  71. // ODMemoryHook::ODMemoryHook
  72. //----------------------------------------------------------------------------------------
  73. #pragma segment HeapSeg
  74.  
  75. ODMemoryHook::ODMemoryHook()
  76. {
  77.     fNextHook = fPreviousHook = this;
  78. }
  79. #endif
  80.  
  81. #if MM_DEBUG
  82. //----------------------------------------------------------------------------------------
  83. // ODMemoryHook::~ODMemoryHook
  84. //----------------------------------------------------------------------------------------
  85. #pragma segment HeapSeg
  86.  
  87. ODMemoryHook::~ODMemoryHook()
  88. {
  89. }
  90. #endif
  91.  
  92. #if MM_DEBUG
  93. //----------------------------------------------------------------------------------------
  94. // ODMemoryHook::operator new
  95. //----------------------------------------------------------------------------------------
  96. #pragma segment HeapSeg
  97.  
  98. void* ODMemoryHook::operator new(SIZE_T size, MMHeapLocation src)
  99. {
  100.     return PlatformAllocateBlock(size, src);
  101. }
  102. #endif
  103.  
  104. #if MM_DEBUG
  105. //----------------------------------------------------------------------------------------
  106. // ODMemoryHook::operator delete
  107. //----------------------------------------------------------------------------------------
  108. #pragma segment HeapSeg
  109.  
  110. void ODMemoryHook::operator delete(void* ptr)
  111. {
  112.         PlatformFreeBlock(ptr);
  113. }
  114. #endif
  115.  
  116. #if MM_DEBUG
  117. //----------------------------------------------------------------------------------------
  118. // ODMemoryHook::GetHeaderSize
  119. //----------------------------------------------------------------------------------------
  120. #pragma segment HeapSeg
  121.  
  122. ODBlockSize ODMemoryHook::GetHeaderSize()
  123. {
  124.     return 0;
  125. }
  126. #endif
  127.  
  128. #if MM_DEBUG
  129. //----------------------------------------------------------------------------------------
  130. // ODMemoryHook::AboutToAllocate
  131. //----------------------------------------------------------------------------------------
  132. #pragma segment HeapSeg
  133.  
  134. ODBlockSize ODMemoryHook::AboutToAllocate(ODBlockSize size) const
  135. {
  136.     return size;
  137. }
  138. #endif
  139.  
  140. #if MM_DEBUG
  141. //----------------------------------------------------------------------------------------
  142. // ODMemoryHook::DidAllocate
  143. //----------------------------------------------------------------------------------------
  144. #pragma segment HeapSeg
  145.  
  146. void *ODMemoryHook::DidAllocate(void* blk, ODBlockSize)
  147. {
  148.     return blk;
  149. }
  150. #endif
  151.  
  152. #if MM_DEBUG
  153. //----------------------------------------------------------------------------------------
  154. // ODMemoryHook::AboutToBlockSize
  155. //----------------------------------------------------------------------------------------
  156. #pragma segment HeapSeg
  157.  
  158. const void *ODMemoryHook::AboutToBlockSize(const void* blk)
  159. {
  160.     return blk;
  161. }
  162. #endif
  163.  
  164. #if MM_DEBUG
  165. //----------------------------------------------------------------------------------------
  166. // ODMemoryHook::AboutToFree
  167. //----------------------------------------------------------------------------------------
  168. #pragma segment HeapSeg
  169.  
  170. void *ODMemoryHook::AboutToFree(void* blk)
  171. {
  172.     return blk;
  173. }
  174. #endif
  175.  
  176. #if MM_DEBUG
  177. //----------------------------------------------------------------------------------------
  178. // ODMemoryHook::AboutToRealloc
  179. //----------------------------------------------------------------------------------------
  180. #pragma segment HeapSeg
  181.  
  182. void ODMemoryHook::AboutToRealloc(void* &, ODBlockSize &)
  183. {
  184. }
  185. #endif
  186.  
  187. #if MM_DEBUG
  188. //----------------------------------------------------------------------------------------
  189. // ODMemoryHook::DidRealloc
  190. //----------------------------------------------------------------------------------------
  191. #pragma segment HeapSeg
  192.  
  193. void *ODMemoryHook::DidRealloc(void *oldBlk, void *blk, ODBlockSize)
  194. {
  195.     return blk;
  196. }
  197. #endif
  198.  
  199. #if MM_DEBUG
  200. //----------------------------------------------------------------------------------------
  201. // ODMemoryHook::AboutToReset
  202. //----------------------------------------------------------------------------------------
  203. #pragma segment HeapSeg
  204.  
  205. void ODMemoryHook::AboutToReset()
  206. {
  207. }
  208. #endif
  209.  
  210. #if MM_DEBUG
  211. //----------------------------------------------------------------------------------------
  212. // ODMemoryHook::Comment
  213. //----------------------------------------------------------------------------------------
  214. #pragma segment HeapSeg
  215.  
  216. void ODMemoryHook::Comment(const char*)
  217. {
  218. }
  219. #endif
  220.  
  221. #if MM_DEBUG
  222. //----------------------------------------------------------------------------------------
  223. // ODMemoryHook::GetType
  224. //----------------------------------------------------------------------------------------
  225. #pragma segment HeapSeg
  226.  
  227. long ODMemoryHook::GetType() const
  228. {
  229.     return ODMemoryHook::kNoType;
  230. }
  231. #endif
  232.  
  233.  
  234. //========================================================================================
  235. // CLASS MemoryHookList (MM_DEBUG only)
  236. //========================================================================================
  237.  
  238. #if MM_DEBUG
  239. //----------------------------------------------------------------------------------------
  240. // MemoryHookList::MemoryHookList
  241. //----------------------------------------------------------------------------------------
  242. #pragma segment HeapSeg
  243.  
  244. MemoryHookList::MemoryHookList()
  245. {
  246. }
  247. #endif
  248.  
  249. #if MM_DEBUG
  250. //----------------------------------------------------------------------------------------
  251. // MemoryHookList::Add
  252. //----------------------------------------------------------------------------------------
  253. #pragma segment HeapSeg
  254.  
  255. void MemoryHookList::Add(ODMemoryHook* aMemoryHook)
  256. {
  257.     // Add at the fEnd of the list by adding after the last hook in the list.
  258.     
  259.     ODMemoryHook* afterHook = fHead.fPreviousHook;
  260.     
  261.     aMemoryHook->fNextHook = afterHook->fNextHook;
  262.     afterHook->fNextHook->fPreviousHook = aMemoryHook;
  263.     aMemoryHook->fPreviousHook = afterHook;
  264.     afterHook->fNextHook = aMemoryHook;
  265. }
  266. #endif
  267.  
  268. #if MM_DEBUG
  269. //----------------------------------------------------------------------------------------
  270. // MemoryHookList::Remove
  271. //----------------------------------------------------------------------------------------
  272. #pragma segment HeapSeg
  273.  
  274. void MemoryHookList::Remove(ODMemoryHook* aMemoryHook)
  275. {
  276.     aMemoryHook->fPreviousHook->fNextHook = aMemoryHook->fNextHook;
  277.     aMemoryHook->fNextHook->fPreviousHook = aMemoryHook->fPreviousHook;
  278. }
  279. #endif
  280.  
  281. #if MM_DEBUG
  282. //----------------------------------------------------------------------------------------
  283. // MemoryHookList::First
  284. //----------------------------------------------------------------------------------------
  285. #pragma segment HeapSeg
  286.  
  287. ODMemoryHook* MemoryHookList::First() const
  288. {
  289.     ODMemoryHook *h = fHead.fNextHook;
  290.     return h != &fHead ? h : NULL;
  291. }
  292. #endif
  293.  
  294. #if MM_DEBUG
  295. //----------------------------------------------------------------------------------------
  296. // MemoryHookList::Next
  297. //----------------------------------------------------------------------------------------
  298. #pragma segment HeapSeg
  299.  
  300. ODMemoryHook* MemoryHookList::After( ODMemoryHook *h ) const
  301. {
  302.     h = h->fNextHook;
  303.     return h != &fHead ? h : NULL;
  304. }
  305. #endif
  306.  
  307. #if MM_DEBUG
  308. //----------------------------------------------------------------------------------------
  309. // MemoryHookList::Previous
  310. //----------------------------------------------------------------------------------------
  311. #pragma segment HeapSeg
  312.  
  313. ODMemoryHook* MemoryHookList::Before( ODMemoryHook *h ) const
  314. {
  315.     h = h->fPreviousHook;
  316.     return h != &fHead ? h : NULL;
  317. }
  318. #endif
  319.  
  320. #if MM_DEBUG
  321. //----------------------------------------------------------------------------------------
  322. // MemoryHookList::Last
  323. //----------------------------------------------------------------------------------------
  324. #pragma segment HeapSeg
  325.  
  326. ODMemoryHook* MemoryHookList::Last() const
  327. {
  328.     ODMemoryHook *h = fHead.fPreviousHook;
  329.     return h != &fHead ? h : NULL;
  330. }
  331. #endif
  332.  
  333. #if MM_DEBUG
  334. //----------------------------------------------------------------------------------------
  335. // MemoryHookList::~MemoryHookList
  336. //----------------------------------------------------------------------------------------
  337. #pragma segment HeapSeg
  338.  
  339. MemoryHookList::~MemoryHookList()
  340. {
  341.     for (ODMemoryHook *hook = First(); hook != NULL; hook = First())
  342.     {
  343.         Remove(hook);
  344.         delete hook;
  345.     }
  346. }
  347. #endif
  348.  
  349.  
  350. //========================================================================================
  351. // CLASS MemoryHeap
  352. //========================================================================================
  353.  
  354. const char *MemoryHeap::kDefaultDescription = "Give this MemoryHeap a description";
  355. const char *MemoryHeap::kDeadHeapDescription = "Dead heap, dead heap, dead heap!";
  356. MemoryHeap *MemoryHeap::fHeapList;                                // Don't initialize!
  357.  
  358. //----------------------------------------------------------------------------------------
  359. // MemoryHeap::ValidateMagicNumber  (MM_DEBUG only)
  360. //----------------------------------------------------------------------------------------
  361.  
  362. #if MM_DEBUG
  363.  
  364.     #pragma segment HeapSeg
  365.     MMBoolean MemoryHeap::ValidateMagicNumber( ) const /* Adkins -- made ValidateMagicNumber( ) const */
  366.     {
  367.         if( fMagicNumber != kMagicNumber ) {
  368.             MM_WARN("Invalid magic number for heap %d -- is this a valid heap?",this);
  369.             return kMMFalse;
  370.         } else
  371.             return kMMTrue;
  372.     }
  373.     
  374. #endif
  375.  
  376. //----------------------------------------------------------------------------------------
  377. // MemoryHeap::GetFirstHeap
  378. //----------------------------------------------------------------------------------------
  379. #pragma segment HeapSeg
  380.  
  381. MemoryHeap *MemoryHeap::GetFirstHeap()
  382. {
  383.     return fHeapList;
  384. }
  385.  
  386. //----------------------------------------------------------------------------------------
  387. // MemoryHeap::Allocate
  388. //----------------------------------------------------------------------------------------
  389. #pragma segment HeapSeg
  390.  
  391. void *MemoryHeap::Allocate(ODBlockSize size)
  392. {
  393.     this->ValidateMagicNumber();
  394.  
  395.     ODBlockSize originalSize = size;
  396. #if MM_DEBUG
  397.     size = this->CallAboutToAllocateHooks(size);
  398. #endif
  399.  
  400.     ODBlockSize allocatedSize;
  401.     void *blk = this->DoAllocate( size, allocatedSize);
  402.     
  403.     if( blk==kMMNULL && originalSize<=fSlushFundAllocSizeLimit ) {
  404.         // Free slush fund. Do not try again, let the caller know it ran out of memory.
  405.         // But a little memory will now be available to make cleanup possible.
  406.         MM_WARN( this->GetSlushFundSize()>0 ?"Out of memory. Freed slush fund."
  407.                                             :"Out of memory, no slush fund. Oh, dear." );
  408.         this->FreeSlushFund();
  409.     }
  410.     
  411.     if (blk != kMMNULL)
  412.     {
  413.         if (fZapOnAllocate)
  414.             PlatformZapMem(blk,allocatedSize,0xBBBBBBBB);
  415.         fBytesAllocated += allocatedSize;
  416.         fNumberAllocatedBlocks++;
  417.     }
  418.  
  419. #if MM_DEBUG
  420.     blk = this->CallDidAllocateHooks(blk, size);
  421. #endif
  422.  
  423.     return blk;
  424. }
  425.  
  426. //----------------------------------------------------------------------------------------
  427. // MemoryHeap::BlockSize
  428. //----------------------------------------------------------------------------------------
  429. #pragma segment HeapSeg
  430.  
  431. ODBlockSize MemoryHeap::BlockSize(const void *blk) const
  432. {
  433.     this->ValidateMagicNumber();
  434.  
  435.     if (blk == NULL)
  436.         return 0;
  437.         
  438. #if MM_DEBUG
  439.     if (fAutoValidation)
  440.         this->ValidateAndReport((void*)blk);
  441.         
  442.     blk = ((MemoryHeap *) this)->CallAboutToBlockSizeHooks((void*)blk);
  443. #endif
  444.  
  445.     ODBlockSize size = this->DoBlockSize((void*)blk);
  446.  
  447. #if MM_DEBUG
  448.     size -= this->CallAboutToAllocateHooks(0);        // Subtract hook pad size
  449. #endif
  450.     return size;
  451. }
  452.  
  453. //----------------------------------------------------------------------------------------
  454. // MemoryHeap::BytesAllocated
  455. //----------------------------------------------------------------------------------------
  456. #pragma segment HeapSeg
  457.  
  458. unsigned long MemoryHeap::BytesAllocated() const
  459. {
  460.     this->ValidateMagicNumber();
  461.  
  462.     return fBytesAllocated;
  463. }
  464.  
  465. //----------------------------------------------------------------------------------------
  466. // MemoryHeap::Free
  467. //----------------------------------------------------------------------------------------
  468. #pragma segment HeapSeg
  469.  
  470. void MemoryHeap::Free(void* blk)
  471. {
  472.     this->ValidateMagicNumber();
  473.  
  474.     if (blk == NULL)
  475.         return;
  476.         
  477. #if MM_DEBUG
  478.     if (fAutoValidation)
  479.         this->ValidateAndReport(blk);
  480.         
  481.     blk = this->CallAboutToFreeHooks(blk);
  482. #endif
  483.     
  484.     ODBlockSize allocatedSize = (ODBlockSize) this->DoBlockSize(blk);
  485.     
  486.     if (fZapOnFree)
  487.             PlatformZapMem(blk,allocatedSize,0xDDDDDDDD);
  488.  
  489.     this->DoFree(blk);
  490.  
  491.     fBytesAllocated -= allocatedSize;
  492.     fNumberAllocatedBlocks--;
  493. }
  494.  
  495. //----------------------------------------------------------------------------------------
  496. // MemoryHeap::LargestFreeBlock
  497. //----------------------------------------------------------------------------------------
  498. #pragma segment HeapSeg
  499.  
  500. unsigned long MemoryHeap::LargestFreeBlock( ) const
  501. {
  502.     long result = this->DoLargestFreeBlock();
  503. #if MM_DEBUG
  504.     result -= this->CallAboutToAllocateHooks(0);
  505. #endif
  506.     return result>0 ?result :0;
  507. }
  508.  
  509. #if MM_DEBUG
  510. //----------------------------------------------------------------------------------------
  511. // MemoryHeap::GetAutoValidation (MM_DEBUG only)
  512. //----------------------------------------------------------------------------------------
  513. #pragma segment HeapSeg
  514.  
  515. Boolean MemoryHeap::GetAutoValidation() const
  516. {
  517.     this->ValidateMagicNumber();
  518.  
  519.     return fAutoValidation;
  520. }
  521. #endif
  522.  
  523. //----------------------------------------------------------------------------------------
  524. // MemoryHeap::GetDescription
  525. //----------------------------------------------------------------------------------------
  526. #pragma segment HeapSeg
  527.  
  528. const char *MemoryHeap::GetDescription() const
  529. {
  530.     this->ValidateMagicNumber();
  531.  
  532.     return fDescription;
  533. }
  534.  
  535. //----------------------------------------------------------------------------------------
  536. // MemoryHeap::GetNextHeap
  537. //----------------------------------------------------------------------------------------
  538. #pragma segment HeapSeg
  539.  
  540. MemoryHeap *MemoryHeap::GetNextHeap() const
  541. {
  542.     return fNextHeap;
  543. }
  544.  
  545. //----------------------------------------------------------------------------------------
  546. // MemoryHeap::GetZapOnAllocate
  547. //----------------------------------------------------------------------------------------
  548. #pragma segment HeapSeg
  549.  
  550. Boolean MemoryHeap::GetZapOnAllocate() const
  551. {
  552.     this->ValidateMagicNumber();
  553.  
  554.     return fZapOnAllocate;
  555. }
  556.  
  557. //----------------------------------------------------------------------------------------
  558. // MemoryHeap::GetZapOnFree
  559. //----------------------------------------------------------------------------------------
  560. #pragma segment HeapSeg
  561.  
  562. Boolean MemoryHeap::GetZapOnFree() const
  563. {
  564.     this->ValidateMagicNumber();
  565.  
  566.     return fZapOnFree;
  567. }
  568.  
  569. #if MM_DEBUG
  570. //----------------------------------------------------------------------------------------
  571. // MemoryHeap::AdoptHook (MM_DEBUG only)
  572. //----------------------------------------------------------------------------------------
  573. #pragma segment HeapSeg
  574.  
  575. void MemoryHeap::AdoptHook(ODMemoryHook *memoryHook)
  576. {
  577.     this->ValidateMagicNumber();
  578.  
  579.     fMemoryHookList.Add(memoryHook);
  580. }
  581. #endif
  582.  
  583. #if MM_DEBUG
  584. //----------------------------------------------------------------------------------------
  585. // MemoryHeap::IsValidBlock (MM_DEBUG only)
  586. //----------------------------------------------------------------------------------------
  587. #pragma segment HeapSeg
  588.  
  589. Boolean MemoryHeap::IsValidBlock(const void *blk) const
  590. {
  591.     this->ValidateMagicNumber();
  592.  
  593.     if (blk == NULL)
  594.         return false;
  595.     
  596.     blk = this->CallAboutToBlockSizeHooks(blk);
  597.         
  598.     if (this->IsMyBlock(blk))
  599.         return DoIsValidBlock(blk);
  600.     else
  601.         return false;
  602. }
  603. #endif
  604.  
  605. #if MM_DEBUG
  606. //----------------------------------------------------------------------------------------
  607. // MemoryHeap::FindBlockContaining (MM_DEBUG only)
  608. //----------------------------------------------------------------------------------------
  609. #pragma segment HeapSeg
  610.  
  611. MMBoolean MemoryHeap::FindBlockContaining( const void *start, const void *end,
  612.                                             const void* &blockStart, const void* &blockEnd ) const
  613. {
  614.     this->ValidateMagicNumber();
  615.  
  616.     if( ! this->DoFindBlockContaining(start,end, blockStart,blockEnd) )
  617.         return kMMFalse;
  618.     else {
  619.         if( blockStart ) {
  620.             ODBlockSize hdrSize = this->CallGetHeaderSize();
  621.             blockStart = (char*)blockStart + hdrSize;
  622.             blockEnd   = (char*)blockEnd - (this->CallAboutToAllocateHooks(0) - hdrSize);
  623.         }
  624.         return kMMTrue;
  625.     }
  626. }
  627. #endif
  628.  
  629. //----------------------------------------------------------------------------------------
  630. // MemoryHeap::NumberAllocatedBlocks
  631. //----------------------------------------------------------------------------------------
  632. #pragma segment HeapSeg
  633.  
  634. unsigned long MemoryHeap::NumberAllocatedBlocks() const
  635. {
  636.     this->ValidateMagicNumber();
  637.  
  638.     return fNumberAllocatedBlocks;
  639. }
  640.  
  641. //----------------------------------------------------------------------------------------
  642. // MemoryHeap::SetBlockIsObject
  643. //----------------------------------------------------------------------------------------
  644. void MemoryHeap::SetBlockIsObject( void* ptr, Boolean isObject )
  645. {
  646.     this->ValidateMagicNumber();
  647. #if MM_DEBUG
  648.     ptr = (void*) CallAboutToBlockSizeHooks(ptr);
  649. #endif
  650.     this->DoSetBlockIsObject(ptr,isObject );
  651. }
  652.  
  653. //----------------------------------------------------------------------------------------
  654. // MemoryHeap::BlockIsObject
  655. //----------------------------------------------------------------------------------------
  656. Boolean MemoryHeap::BlockIsObject( const void* ptr ) const
  657. {
  658.     this->ValidateMagicNumber();
  659. #if MM_DEBUG
  660.     ptr = CallAboutToBlockSizeHooks(ptr);
  661. #endif
  662.     return this->DoBlockIsObject(ptr);
  663. }
  664.  
  665. #if MM_DEBUG
  666. //----------------------------------------------------------------------------------------
  667. // MemoryHeap::SetBlockStackCrawl
  668. //----------------------------------------------------------------------------------------
  669. void MemoryHeap::SetBlockStackCrawl( const void* blk, StackCrawl *s )
  670. {
  671.     this->ValidateMagicNumber();
  672.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  673.             hook != NULL; hook = fMemoryHookList.Before(hook)) {
  674.         blk = hook->AboutToBlockSize(blk);
  675.         if( hook->GetType() == CBlockStackCrawlHook::kBlockStackCrawlHookType ) {
  676.             ((CBlockStackCrawlHook*)hook)->SetStackCrawl(blk,s);
  677.             return;
  678.         }
  679.     }
  680.     MM_WARN("No BlockStackCrawlHook for SetBlockStackCrawl");
  681. }
  682.  
  683. //----------------------------------------------------------------------------------------
  684. // MemoryHeap::GetBlockStackCrawl
  685. //----------------------------------------------------------------------------------------
  686. StackCrawl* MemoryHeap::GetBlockStackCrawl( const void* blk ) const
  687. {
  688.     this->ValidateMagicNumber();
  689.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  690.             hook != NULL; hook = fMemoryHookList.Before(hook)) {
  691.         blk = hook->AboutToBlockSize(blk);
  692.         if( hook->GetType() == CBlockStackCrawlHook::kBlockStackCrawlHookType ) {
  693.             return ((CBlockStackCrawlHook*)hook)->GetStackCrawl(blk);
  694.         }
  695.     }
  696.     MM_WARN("No BlockStackCrawlHook for GetBlockStackCrawl");
  697.     return NULL;
  698. }
  699. #endif
  700.  
  701. //----------------------------------------------------------------------------------------
  702. // MemoryHeap::GetBlockHeap
  703. //----------------------------------------------------------------------------------------
  704. MemoryHeap* MemoryHeap::GetBlockHeap( const void* ptr ) const
  705. {
  706.     // This makes the assumption (in a debug build) that the block's heap
  707.     // has the same memory hooks installed as this one. In reality this is the
  708.     // case; but at some future point it might cause trouble......
  709.     // In any case this will not occur in a non-debug build.
  710.     
  711.     this->ValidateMagicNumber();
  712. #if MM_DEBUG
  713.     ptr = this->CallAboutToBlockSizeHooks(ptr);
  714. #endif
  715.     return this->DoGetBlockHeap(ptr);
  716. }
  717.  
  718. //----------------------------------------------------------------------------------------
  719. // MemoryHeap::Reallocate
  720. //----------------------------------------------------------------------------------------
  721. #pragma segment HeapSeg
  722.  
  723. void *MemoryHeap::Reallocate(void *blk, ODBlockSize newSize)
  724. {
  725.     this->ValidateMagicNumber();
  726.  
  727.     if (blk == NULL)
  728.         return this->Allocate(newSize);
  729.         
  730.     ODBlockSize allocatedSize;
  731.     ODBlockSize oldBlkSize = (ODBlockSize) this->BlockSize(blk);
  732.     
  733. #if MM_DEBUG
  734.     void *oldBlk = blk;
  735.     this->CallAboutToReallocHooks(blk, newSize);
  736. #endif
  737.     
  738.     blk = this->DoReallocate(blk, newSize, allocatedSize);
  739.     
  740.     if (blk != NULL)
  741.         fBytesAllocated += allocatedSize - oldBlkSize;
  742.             
  743. #if MM_DEBUG
  744.     blk = this->CallDidReallocHooks(oldBlk,blk, newSize);
  745. #endif
  746.  
  747.     return blk;
  748. }
  749.  
  750.  
  751. //----------------------------------------------------------------------------------------
  752. // MemoryHeap::AllocateSlushFund
  753. //----------------------------------------------------------------------------------------
  754. #pragma segment HeapSeg
  755. MMBoolean MemoryHeap::AllocateSlushFund( size_t size, size_t allocSizeLimit )
  756. {
  757.     if( size==0 ) {
  758.         this->FreeSlushFund();
  759.         return kMMTrue;
  760.     }
  761.     this->Free(fSlushFund);
  762.     size_t oldLimit = fSlushFundAllocSizeLimit;
  763.     fSlushFundAllocSizeLimit = 0;
  764.     MMBlock slushy = this->Allocate(size);
  765.     if( !slushy ) {
  766.         if( fSlushFund ) {
  767.             fSlushFund = this->Allocate(fSlushFundSize);
  768.             if( !fSlushFund ) 
  769.                 MM_WARN("Yow! Lost slush fund accidentally");
  770.         }
  771.         return kMMFalse;
  772.     }
  773.     fSlushFund = slushy;
  774.     fSlushFundSize = size;
  775.     fSlushFundAllocSizeLimit = allocSizeLimit;
  776.     return kMMTrue;
  777. }
  778.  
  779. //----------------------------------------------------------------------------------------
  780. // MemoryHeap::FreeSlushFund
  781. //----------------------------------------------------------------------------------------
  782. #pragma segment HeapSeg
  783. size_t MemoryHeap::FreeSlushFund( )
  784. {
  785.     this->Free(fSlushFund);
  786.     fSlushFund = kMMNULL;
  787.     size_t size = fSlushFundSize;
  788.     fSlushFundSize = fSlushFundAllocSizeLimit = 0;
  789.     return size;
  790. }
  791.  
  792. #if MM_DEBUG
  793. //----------------------------------------------------------------------------------------
  794. // MemoryHeap::DeleteHook (MM_DEBUG only)
  795. //----------------------------------------------------------------------------------------
  796. #pragma segment HeapSeg
  797.  
  798. void MemoryHeap::DeleteHook(ODMemoryHook *memoryHook)
  799. {
  800.     this->ValidateMagicNumber();
  801.  
  802.     fMemoryHookList.Remove(memoryHook);
  803. }
  804. #endif
  805.  
  806. //----------------------------------------------------------------------------------------
  807. // MemoryHeap::Reset
  808. //----------------------------------------------------------------------------------------
  809. #pragma segment HeapSeg
  810.  
  811. void MemoryHeap::Reset()
  812. {
  813.     this->ValidateMagicNumber();
  814.  
  815. #if MM_DEBUG
  816.     this->CallAboutToResetHooks();
  817. #endif
  818.     
  819.     fBytesAllocated = 0;
  820.     fNumberAllocatedBlocks = 0;
  821.     
  822.     this->DoReset();
  823. }
  824.  
  825. #if MM_DEBUG
  826. //----------------------------------------------------------------------------------------
  827. // MemoryHeap::SetAutoValidation (MM_DEBUG only)
  828. //----------------------------------------------------------------------------------------
  829. #pragma segment HeapSeg
  830.  
  831. void MemoryHeap::SetAutoValidation(Boolean autoValidation)
  832. {
  833.     this->ValidateMagicNumber();
  834.  
  835.     fAutoValidation = autoValidation;
  836. }
  837. #endif
  838.  
  839. //----------------------------------------------------------------------------------------
  840. // MemoryHeap::SetDescription
  841. //----------------------------------------------------------------------------------------
  842. #pragma segment HeapSeg
  843.  
  844. void MemoryHeap::SetDescription(const char *description)
  845. {
  846.     this->ValidateMagicNumber();
  847.  
  848.     // ------ Set the description without depending on other code
  849.     
  850.     const char *src = description;
  851.     char *dst = fDescription;
  852.     int i;
  853.     
  854.     for (i = 0; i < kDescriptionLength - 1 && *src; i++)
  855.         *dst++ = *src++;
  856.     fDescription[i] = 0;
  857. }
  858.  
  859. //----------------------------------------------------------------------------------------
  860. // MemoryHeap::SetZapOnAllocate
  861. //----------------------------------------------------------------------------------------
  862. #pragma segment HeapSeg
  863.  
  864. void MemoryHeap::SetZapOnAllocate(Boolean zapOnAllocate)
  865. {
  866.     this->ValidateMagicNumber();
  867.  
  868.     fZapOnAllocate = zapOnAllocate;
  869. }
  870.  
  871. //----------------------------------------------------------------------------------------
  872. // MemoryHeap::SetZapOnFree
  873. //----------------------------------------------------------------------------------------
  874. #pragma segment HeapSeg
  875.  
  876. void MemoryHeap::SetZapOnFree(Boolean zapOnFree)
  877. {
  878.     this->ValidateMagicNumber();
  879.  
  880.     fZapOnFree = zapOnFree;
  881. }
  882.  
  883. //----------------------------------------------------------------------------------------
  884. // MemoryHeap::~MemoryHeap
  885. //----------------------------------------------------------------------------------------
  886. #pragma segment HeapSeg
  887.  
  888. MemoryHeap::~MemoryHeap()
  889. {
  890.     this->ValidateMagicNumber();
  891.  
  892.     // ----- Remove from the static list of heaps
  893.     
  894.     MemoryHeap *lastHeap = NULL, *currentHeap = fHeapList;
  895.     
  896.     while (currentHeap != NULL)
  897.     {
  898.         if (this == currentHeap)
  899.         {
  900.             if (lastHeap == NULL)
  901.                 fHeapList = currentHeap->GetNextHeap();
  902.             else
  903.                 lastHeap->fNextHeap = currentHeap->GetNextHeap();
  904.             
  905.             currentHeap = NULL;
  906.         }
  907.         else
  908.         {
  909.             lastHeap = currentHeap;
  910.             currentHeap = currentHeap->GetNextHeap();
  911.         }
  912.     }
  913.  
  914.     // ------ Set the default description without depending on other code
  915.     
  916.     const char *src = kDeadHeapDescription;
  917.     char *dst = fDescription;    
  918.     for (; *src;)
  919.         *dst++ = *src++;
  920.     *dst = 0;
  921.     
  922.     fMagicNumber = 0;
  923. }
  924.  
  925. //----------------------------------------------------------------------------------------
  926. // MemoryHeap::MemoryHeap
  927. //----------------------------------------------------------------------------------------
  928. #pragma segment HeapSeg
  929.  
  930. MemoryHeap::MemoryHeap(Boolean autoValidation,
  931.                        Boolean zapOnAllocate,
  932.                        Boolean zapOnFree,
  933.                        MMHeapLocation memSrc) :
  934.     fAutoValidation(autoValidation),
  935.     fZapOnAllocate(zapOnAllocate),
  936.     fZapOnFree(zapOnFree),
  937.     fBytesAllocated(0),
  938.     fNumberAllocatedBlocks(0),
  939.     fMemSource(memSrc),
  940.     fMagicNumber(kMagicNumber),
  941.     fSlushFund(kMMNULL),
  942.     fSlushFundSize(0),
  943.     fSlushFundAllocSizeLimit(0)
  944. {
  945.     // ------ Set the default description without depending on other code
  946.     
  947.     const char *src = kDefaultDescription;
  948.     char *dst = fDescription;    
  949.     for (; *src;)
  950.         *dst++ = *src++;
  951.     *dst = 0;
  952.     
  953.     // Add to the static list of heaps
  954.     
  955.     fNextHeap = fHeapList;
  956.     fHeapList = this;
  957. }
  958.  
  959. //----------------------------------------------------------------------------------------
  960. // MemoryHeap::operator new
  961. //----------------------------------------------------------------------------------------
  962. #pragma segment HeapSeg
  963.  
  964. void* MemoryHeap::operator new(SIZE_T size, MMHeapLocation src)
  965. {
  966.     return PlatformAllocateBlock(size, src);
  967. }
  968.  
  969. //----------------------------------------------------------------------------------------
  970. // MemoryHeap::operator delete
  971. //----------------------------------------------------------------------------------------
  972. #pragma segment HeapSeg
  973.  
  974. void MemoryHeap::operator delete(void* ptr)
  975. {
  976.         PlatformFreeBlock(ptr);
  977. }
  978.  
  979. //----------------------------------------------------------------------------------------
  980. // MemoryHeap::AllocateRawMemory
  981. //----------------------------------------------------------------------------------------
  982. #pragma segment HeapSeg
  983.  
  984. void *MemoryHeap::AllocateRawMemory(ODBlockSize size)
  985. {
  986.     return PlatformAllocateBlock(size, fMemSource);
  987. }
  988.  
  989. //----------------------------------------------------------------------------------------
  990. // MemoryHeap::DoReallocate
  991. //----------------------------------------------------------------------------------------
  992. #pragma segment HeapSeg
  993.  
  994. void *MemoryHeap::DoReallocate(void *block, ODBlockSize newSize, ODBlockSize &allocatedSize)
  995. {
  996.     ODBlockSize oldRealSize = this->DoBlockSize(block);
  997.     void* newBlock = this->DoAllocate(newSize, allocatedSize);
  998.     
  999.     if (newBlock != NULL)
  1000.     {
  1001.         ODBlockSize copySize = newSize <= oldRealSize ? newSize : oldRealSize;
  1002.         PlatformCopyMemory(block, newBlock, copySize);
  1003.  
  1004.         if (fZapOnFree)
  1005.         {
  1006.             char *chrBlk = (char *) block;
  1007.             for (ODBlockSize i = 0; i < oldRealSize; i++)
  1008.                 *chrBlk++ = 0xDD;
  1009.         }
  1010.  
  1011.         this->DoFree(block);
  1012.     }
  1013.     else
  1014.       if (newSize <= oldRealSize)   //if unable to get new fMem, and newSize is <= real size
  1015.         return block;               //then return original ptr unchanged
  1016.  
  1017.     return newBlock;
  1018. }
  1019.         
  1020. //----------------------------------------------------------------------------------------
  1021. // MemoryHeap::FreeRawMemory
  1022. //----------------------------------------------------------------------------------------
  1023. #pragma segment HeapSeg
  1024.  
  1025. void MemoryHeap::FreeRawMemory(void* ptr)
  1026. {
  1027.     PlatformFreeBlock(ptr);
  1028. }
  1029.  
  1030. #if MM_DEBUG
  1031. //----------------------------------------------------------------------------------------
  1032. // MemoryHeap::CompilerCheck (MM_DEBUG only)
  1033. //----------------------------------------------------------------------------------------
  1034. #pragma segment HeapSeg
  1035.  
  1036. void MemoryHeap::CompilerCheck()
  1037. {
  1038. }
  1039. #endif
  1040.  
  1041. #if MM_DEBUG
  1042. //----------------------------------------------------------------------------------------
  1043. // MemoryHeap::CallAboutToAllocateHooks (MM_DEBUG only)
  1044. //----------------------------------------------------------------------------------------
  1045. #pragma segment HeapSeg
  1046.  
  1047. ODBlockSize MemoryHeap::CallAboutToAllocateHooks(ODBlockSize size) const
  1048. {
  1049.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1050.             hook != NULL; hook = fMemoryHookList.After(hook))
  1051.         size = hook->AboutToAllocate(size);
  1052.         
  1053.     return size;
  1054. }
  1055. #endif
  1056.  
  1057. #if MM_DEBUG
  1058. //----------------------------------------------------------------------------------------
  1059. // MemoryHeap::CallGetHeaderSize (MM_DEBUG only)
  1060. //----------------------------------------------------------------------------------------
  1061. #pragma segment HeapSeg
  1062.  
  1063. ODBlockSize MemoryHeap::CallGetHeaderSize() const
  1064. {
  1065.     ODBlockSize size = 0;
  1066.     
  1067.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1068.             hook != NULL; hook = fMemoryHookList.After(hook))
  1069.         size += hook->GetHeaderSize();
  1070.         
  1071.     return size;
  1072. }
  1073. #endif
  1074.  
  1075. #if MM_DEBUG
  1076. //----------------------------------------------------------------------------------------
  1077. // MemoryHeap::CallDidAllocateHooks (MM_DEBUG only)
  1078. //----------------------------------------------------------------------------------------
  1079. #pragma segment HeapSeg
  1080.  
  1081. void *MemoryHeap::CallDidAllocateHooks(void* blk, ODBlockSize size)
  1082. {
  1083.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1084.             hook != NULL; hook = fMemoryHookList.After(hook)) {
  1085.         blk = hook->DidAllocate(blk, size);
  1086.         size -= hook->AboutToAllocate(0);
  1087.     }
  1088.     return blk;
  1089. }
  1090. #endif
  1091.  
  1092. #if MM_DEBUG
  1093. //----------------------------------------------------------------------------------------
  1094. // MemoryHeap::CallAboutToBlockSizeHooks (MM_DEBUG only)
  1095. //----------------------------------------------------------------------------------------
  1096. #pragma segment HeapSeg
  1097.  
  1098. const void *MemoryHeap::CallAboutToBlockSizeHooks(const void* blk) const
  1099. {
  1100.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  1101.             hook != NULL; hook = fMemoryHookList.Before(hook))
  1102.         blk = hook->AboutToBlockSize(blk);
  1103.         
  1104.     return (void*) blk;
  1105. }
  1106. #endif
  1107.  
  1108. #if MM_DEBUG
  1109. //----------------------------------------------------------------------------------------
  1110. // MemoryHeap::CallAboutToFreeHooks (MM_DEBUG only)
  1111. //----------------------------------------------------------------------------------------
  1112. #pragma segment HeapSeg
  1113.  
  1114. void *MemoryHeap::CallAboutToFreeHooks(void* blk)
  1115. {
  1116.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  1117.             hook != NULL; hook = fMemoryHookList.Before(hook))
  1118.         blk = hook->AboutToFree(blk);
  1119.         
  1120.     return blk;
  1121. }
  1122. #endif
  1123.  
  1124. #if MM_DEBUG
  1125. //----------------------------------------------------------------------------------------
  1126. // MemoryHeap::CallAboutToReallocHooks (MM_DEBUG only)
  1127. //----------------------------------------------------------------------------------------
  1128. #pragma segment HeapSeg
  1129.  
  1130. void MemoryHeap::CallAboutToReallocHooks(void* &blk, ODBlockSize& size)
  1131. {
  1132.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  1133.             hook != NULL; hook = fMemoryHookList.Before(hook))
  1134.         hook->AboutToRealloc(blk, size);
  1135. }
  1136. #endif
  1137.  
  1138. #if MM_DEBUG
  1139. //----------------------------------------------------------------------------------------
  1140. // MemoryHeap::CallDidReallocHooks (MM_DEBUG only)
  1141. //----------------------------------------------------------------------------------------
  1142. #pragma segment HeapSeg
  1143.  
  1144. void *MemoryHeap::CallDidReallocHooks(void *oldBlk, void *blk, ODBlockSize size)
  1145. {
  1146.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1147.             hook != NULL; hook = fMemoryHookList.After(hook)) {
  1148.         blk = hook->DidRealloc(oldBlk, blk, size);
  1149.         size -= hook->AboutToAllocate(0);
  1150.     }
  1151.     return blk;
  1152. }
  1153. #endif
  1154.  
  1155. #if MM_DEBUG
  1156. //----------------------------------------------------------------------------------------
  1157. // MemoryHeap::CallAboutToResetHooks (MM_DEBUG only)
  1158. //----------------------------------------------------------------------------------------
  1159. #pragma segment HeapSeg
  1160.  
  1161. void MemoryHeap::CallAboutToResetHooks()
  1162. {
  1163.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1164.             hook != NULL; hook = fMemoryHookList.After(hook))
  1165.         hook->AboutToReset();
  1166. }
  1167. #endif
  1168.  
  1169. #if MM_DEBUG
  1170. //----------------------------------------------------------------------------------------
  1171. // MemoryHeap::CallCommentHooks (MM_DEBUG only)
  1172. //----------------------------------------------------------------------------------------
  1173. #pragma segment HeapSeg
  1174.  
  1175. void MemoryHeap::CallCommentHooks(const char* comment)
  1176. {
  1177.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1178.             hook != NULL; hook = fMemoryHookList.After(hook))
  1179.         hook->Comment(comment);
  1180. }
  1181. #endif
  1182.  
  1183. #if MM_DEBUG
  1184. //----------------------------------------------------------------------------------------
  1185. // MemoryHeap::ValidateAndReport (MM_DEBUG only)
  1186. //----------------------------------------------------------------------------------------
  1187. #pragma segment HeapSeg
  1188.  
  1189. void MemoryHeap::ValidateAndReport(void *blk) const
  1190. {
  1191.     MM_ASSERT(this->IsValidBlock(blk));
  1192. }
  1193. #endif
  1194.