Alloc.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "ParserPch.h"
  6. #if DEBUG
  7. #define DEBUG_TRASHMEM(pv, cb) memset(pv, 0xbc, cb)
  8. #else
  9. #define DEBUG_TRASHMEM
  10. #endif //DEBUG
  11. #if TARGET_64
  12. struct __ALIGN_FOO__ {
  13. int w1;
  14. double dbl;
  15. };
  16. #define ALIGN_FULL (offsetof(__ALIGN_FOO__, dbl))
  17. #else
  18. // Force check for 4 byte alignment to support Win98/ME
  19. #define ALIGN_FULL 4
  20. #endif // TARGET_64
  21. #define AlignFull(VALUE) (~(~((VALUE) + (ALIGN_FULL-1)) | (ALIGN_FULL-1)))
  22. NoReleaseAllocator::NoReleaseAllocator(int32 cbFirst, int32 cbMax)
  23. : m_pblkList(NULL)
  24. , m_ibCur(0)
  25. , m_ibMax(0)
  26. , m_cbMinBlock(cbFirst)
  27. , m_cbMaxBlock(cbMax)
  28. #if DEBUG
  29. , m_cbTotRequested(0)
  30. , m_cbTotAlloced(0)
  31. , m_cblk(0)
  32. , m_cpvBig(0)
  33. , m_cpvSmall(0)
  34. #endif
  35. {
  36. // require reasonable ranges
  37. Assert((0 < cbFirst) && (cbFirst < SHRT_MAX/2));
  38. Assert((0 < cbMax ) && (cbMax < SHRT_MAX));
  39. }
  40. void * NoReleaseAllocator::Alloc(int32 cb)
  41. {
  42. Assert(cb > 0);
  43. if (cb <= 0)
  44. return NULL;
  45. const int32 kcbHead = AlignFull(sizeof(NoReleaseAllocator::NraBlock));
  46. void * pv;
  47. if (cb > m_ibMax - m_ibCur)
  48. {
  49. int32 cbBlock;
  50. int32 cbAlloc;
  51. NraBlock * pblk;
  52. if (cb >= m_cbMaxBlock)
  53. {
  54. // check for integer overflow before allocating (See WindowsSE #88972)
  55. cbAlloc = cb + kcbHead;
  56. if (cbAlloc < cb)
  57. {
  58. Assert(FALSE); // too big!
  59. return NULL;
  60. }
  61. // create a chunk just for this allocation
  62. pblk = (NraBlock *)malloc(cbAlloc);
  63. if (NULL == pblk)
  64. return NULL;
  65. #if DEBUG
  66. m_cbTotAlloced += cbAlloc;
  67. m_cbTotRequested += cb;
  68. m_cpvBig++;
  69. m_cblk++;
  70. #endif //DEBUG
  71. if (m_ibCur < m_ibMax)
  72. {
  73. // There is still room in current block, so put the new block
  74. // after the current block.
  75. pblk->pblkNext = m_pblkList->pblkNext;
  76. m_pblkList->pblkNext = pblk;
  77. }
  78. else
  79. {
  80. // Link into front of the list.
  81. // Don't need to adjust m_ibCur and m_ibMax, because they
  82. // already have the correct relationship for this full block
  83. // (m_ibCur >= m_ibMax) and the actual values will not be
  84. // used.
  85. pblk->pblkNext = m_pblkList;
  86. m_pblkList = pblk;
  87. }
  88. DEBUG_TRASHMEM((byte *)pblk + kcbHead, cb);
  89. return (byte *)pblk + kcbHead;
  90. }
  91. cbBlock = cb; // requested size
  92. if (m_ibMax > cbBlock) // at least current block size
  93. cbBlock = m_ibMax;
  94. cbBlock += cbBlock; // *2 (can overflow, but checked below)
  95. if (m_cbMinBlock > cbBlock) // at least minimum size
  96. cbBlock = m_cbMinBlock;
  97. if (cbBlock > m_cbMaxBlock) // no larger than the max
  98. cbBlock = m_cbMaxBlock;
  99. if (cb > cbBlock) // guarantee it's big enough
  100. {
  101. Assert(("Request too large", FALSE));
  102. return NULL;
  103. }
  104. // check for integer overflow before allocating (See WindowsSE #88972)
  105. cbAlloc = cbBlock + kcbHead;
  106. if ((cbAlloc < cbBlock) || (cbAlloc < cb))
  107. {
  108. Assert(FALSE); // too big!
  109. return NULL ;
  110. }
  111. // allocate a new block
  112. pblk = (NraBlock *)malloc(cbAlloc);
  113. #ifdef MEM_TRACK
  114. RegisterAlloc((char*)pblk,cbAlloc);
  115. #endif
  116. if (NULL == pblk)
  117. return NULL;
  118. #if DEBUG
  119. m_cbTotAlloced += cbAlloc;
  120. m_cblk++;
  121. #endif //DEBUG
  122. pblk->pblkNext = m_pblkList;
  123. m_pblkList = pblk;
  124. m_ibMax = cbBlock;
  125. m_ibCur = 0;
  126. }
  127. Assert(m_ibCur + cb <= m_ibMax);
  128. #if DEBUG
  129. m_cbTotRequested += cb;
  130. m_cpvSmall++;
  131. #endif //DEBUG
  132. pv = (byte *)m_pblkList + kcbHead + m_ibCur;
  133. DEBUG_TRASHMEM(pv, cb);
  134. m_ibCur += (int32)AlignFull(cb);
  135. Assert(m_ibCur >= 0);
  136. return pv;
  137. }
  138. void NoReleaseAllocator::FreeAll(void)
  139. {
  140. // Free all of the allocated blocks
  141. while (NULL != m_pblkList)
  142. {
  143. NraBlock * pblk = m_pblkList;
  144. #pragma prefast(suppress:6001, "Not sure why it is complaining *m_plkList is uninitialized")
  145. m_pblkList = pblk->pblkNext;
  146. free(pblk);
  147. }
  148. // prepare for next round of allocations
  149. m_ibCur = m_ibMax = 0;
  150. #if DEBUG
  151. m_cbTotRequested = 0;
  152. m_cbTotAlloced = 0;
  153. m_cblk = 0;
  154. m_cpvBig = 0;
  155. m_cpvSmall = 0;
  156. #endif
  157. }