MarkedSpace.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  3. * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. *
  19. */
  20. #include "config.h"
  21. #include "MarkedSpace.h"
  22. #include "IncrementalSweeper.h"
  23. #include "JSGlobalObject.h"
  24. #include "JSLock.h"
  25. #include "JSObject.h"
  26. namespace JSC {
  27. class Structure;
  28. class Free {
  29. public:
  30. typedef MarkedBlock* ReturnType;
  31. enum FreeMode { FreeOrShrink, FreeAll };
  32. Free(FreeMode, MarkedSpace*);
  33. void operator()(MarkedBlock*);
  34. ReturnType returnValue();
  35. private:
  36. FreeMode m_freeMode;
  37. MarkedSpace* m_markedSpace;
  38. DoublyLinkedList<MarkedBlock> m_blocks;
  39. };
  40. inline Free::Free(FreeMode freeMode, MarkedSpace* newSpace)
  41. : m_freeMode(freeMode)
  42. , m_markedSpace(newSpace)
  43. {
  44. }
  45. inline void Free::operator()(MarkedBlock* block)
  46. {
  47. if (m_freeMode == FreeOrShrink)
  48. m_markedSpace->freeOrShrinkBlock(block);
  49. else
  50. m_markedSpace->freeBlock(block);
  51. }
  52. inline Free::ReturnType Free::returnValue()
  53. {
  54. return m_blocks.head();
  55. }
  56. struct VisitWeakSet : MarkedBlock::VoidFunctor {
  57. VisitWeakSet(HeapRootVisitor& heapRootVisitor) : m_heapRootVisitor(heapRootVisitor) { }
  58. void operator()(MarkedBlock* block) { block->visitWeakSet(m_heapRootVisitor); }
  59. private:
  60. HeapRootVisitor& m_heapRootVisitor;
  61. };
  62. struct ReapWeakSet : MarkedBlock::VoidFunctor {
  63. void operator()(MarkedBlock* block) { block->reapWeakSet(); }
  64. };
  65. MarkedSpace::MarkedSpace(Heap* heap)
  66. : m_heap(heap)
  67. {
  68. for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
  69. allocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::None);
  70. normalDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::Normal);
  71. immortalStructureDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::ImmortalStructure);
  72. }
  73. for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
  74. allocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::None);
  75. normalDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::Normal);
  76. immortalStructureDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::ImmortalStructure);
  77. }
  78. m_normalSpace.largeAllocator.init(heap, this, 0, MarkedBlock::None);
  79. m_normalDestructorSpace.largeAllocator.init(heap, this, 0, MarkedBlock::Normal);
  80. m_immortalStructureDestructorSpace.largeAllocator.init(heap, this, 0, MarkedBlock::ImmortalStructure);
  81. }
  82. MarkedSpace::~MarkedSpace()
  83. {
  84. Free free(Free::FreeAll, this);
  85. forEachBlock(free);
  86. }
  87. struct LastChanceToFinalize : MarkedBlock::VoidFunctor {
  88. void operator()(MarkedBlock* block) { block->lastChanceToFinalize(); }
  89. };
  90. void MarkedSpace::lastChanceToFinalize()
  91. {
  92. canonicalizeCellLivenessData();
  93. forEachBlock<LastChanceToFinalize>();
  94. }
  95. void MarkedSpace::sweep()
  96. {
  97. m_heap->sweeper()->willFinishSweeping();
  98. forEachBlock<Sweep>();
  99. }
  100. void MarkedSpace::resetAllocators()
  101. {
  102. for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
  103. allocatorFor(cellSize).reset();
  104. normalDestructorAllocatorFor(cellSize).reset();
  105. immortalStructureDestructorAllocatorFor(cellSize).reset();
  106. }
  107. for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
  108. allocatorFor(cellSize).reset();
  109. normalDestructorAllocatorFor(cellSize).reset();
  110. immortalStructureDestructorAllocatorFor(cellSize).reset();
  111. }
  112. m_normalSpace.largeAllocator.reset();
  113. m_normalDestructorSpace.largeAllocator.reset();
  114. m_immortalStructureDestructorSpace.largeAllocator.reset();
  115. }
  116. void MarkedSpace::visitWeakSets(HeapRootVisitor& heapRootVisitor)
  117. {
  118. VisitWeakSet visitWeakSet(heapRootVisitor);
  119. forEachBlock(visitWeakSet);
  120. }
  121. void MarkedSpace::reapWeakSets()
  122. {
  123. forEachBlock<ReapWeakSet>();
  124. }
  125. void MarkedSpace::canonicalizeCellLivenessData()
  126. {
  127. for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
  128. allocatorFor(cellSize).canonicalizeCellLivenessData();
  129. normalDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
  130. immortalStructureDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
  131. }
  132. for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
  133. allocatorFor(cellSize).canonicalizeCellLivenessData();
  134. normalDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
  135. immortalStructureDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
  136. }
  137. m_normalSpace.largeAllocator.canonicalizeCellLivenessData();
  138. m_normalDestructorSpace.largeAllocator.canonicalizeCellLivenessData();
  139. m_immortalStructureDestructorSpace.largeAllocator.canonicalizeCellLivenessData();
  140. }
  141. bool MarkedSpace::isPagedOut(double deadline)
  142. {
  143. for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
  144. if (allocatorFor(cellSize).isPagedOut(deadline)
  145. || normalDestructorAllocatorFor(cellSize).isPagedOut(deadline)
  146. || immortalStructureDestructorAllocatorFor(cellSize).isPagedOut(deadline))
  147. return true;
  148. }
  149. for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
  150. if (allocatorFor(cellSize).isPagedOut(deadline)
  151. || normalDestructorAllocatorFor(cellSize).isPagedOut(deadline)
  152. || immortalStructureDestructorAllocatorFor(cellSize).isPagedOut(deadline))
  153. return true;
  154. }
  155. if (m_normalSpace.largeAllocator.isPagedOut(deadline)
  156. || m_normalDestructorSpace.largeAllocator.isPagedOut(deadline)
  157. || m_immortalStructureDestructorSpace.largeAllocator.isPagedOut(deadline))
  158. return true;
  159. return false;
  160. }
  161. void MarkedSpace::freeBlock(MarkedBlock* block)
  162. {
  163. block->allocator()->removeBlock(block);
  164. m_blocks.remove(block);
  165. if (block->capacity() == MarkedBlock::blockSize) {
  166. m_heap->blockAllocator().deallocate(MarkedBlock::destroy(block));
  167. return;
  168. }
  169. m_heap->blockAllocator().deallocateCustomSize(MarkedBlock::destroy(block));
  170. }
  171. void MarkedSpace::freeOrShrinkBlock(MarkedBlock* block)
  172. {
  173. if (!block->isEmpty()) {
  174. block->shrink();
  175. return;
  176. }
  177. freeBlock(block);
  178. }
  179. struct Shrink : MarkedBlock::VoidFunctor {
  180. void operator()(MarkedBlock* block) { block->shrink(); }
  181. };
  182. void MarkedSpace::shrink()
  183. {
  184. Free freeOrShrink(Free::FreeOrShrink, this);
  185. forEachBlock(freeOrShrink);
  186. }
  187. } // namespace JSC