Changeset 52176 in webkit for trunk/JavaScriptCore/runtime
- Timestamp:
- Dec 15, 2009, 2:40:00 PM (15 years ago)
- Location:
- trunk/JavaScriptCore/runtime
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/Collector.cpp
r52090 r52176 170 170 #endif // PLATFORM(SYMBIAN) 171 171 172 memset(&primaryHeap, 0, sizeof(CollectorHeap)); 173 allocateBlock<PrimaryHeap>(); 174 175 memset(&numberHeap, 0, sizeof(CollectorHeap)); 176 #if USE(JSVALUE32) 177 allocateBlock<NumberHeap>(); 178 #endif 172 memset(&m_heap, 0, sizeof(CollectorHeap)); 173 allocateBlock(); 179 174 } 180 175 … … 199 194 m_markListSet = 0; 200 195 201 freeBlocks<PrimaryHeap>(); 202 freeBlocks<NumberHeap>(); 196 freeBlocks(); 203 197 204 198 #if ENABLE(JSC_MULTIPLE_THREADS) … … 219 213 } 220 214 221 template <HeapType heapType>222 215 NEVER_INLINE CollectorBlock* Heap::allocateBlock() 223 216 { … … 274 267 CollectorBlock* block = reinterpret_cast<CollectorBlock*>(address); 275 268 block->heap = this; 276 block->type = heapType; 277 clearMarkBits<heapType>(block); 278 279 // heapAllocate assumes that it's safe to call a destructor on any cell in the primary heap. 280 if (heapType != NumberHeap) { 281 Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get(); 282 for (size_t i = 0; i < HeapConstants<heapType>::cellsPerBlock; ++i) 283 new (block->cells + i) JSCell(dummyMarkableCellStructure); 284 } 269 clearMarkBits(block); 270 271 Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get(); 272 for (size_t i = 0; i < HeapConstants::cellsPerBlock; ++i) 273 new (block->cells + i) JSCell(dummyMarkableCellStructure); 285 274 286 275 // Add block to blocks vector. 287 276 288 CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 289 size_t numBlocks = heap.numBlocks; 290 if (heap.usedBlocks == numBlocks) { 277 size_t numBlocks = m_heap.numBlocks; 278 if (m_heap.usedBlocks == numBlocks) { 291 279 static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR; 292 280 if (numBlocks > maxNumBlocks) 293 281 CRASH(); 294 282 numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); 295 heap.numBlocks = numBlocks;296 heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));297 } 298 heap.blocks[heap.usedBlocks++] = block;283 m_heap.numBlocks = numBlocks; 284 m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, numBlocks * sizeof(CollectorBlock*))); 285 } 286 m_heap.blocks[m_heap.usedBlocks++] = block; 299 287 300 288 return block; 301 289 } 302 290 303 template <HeapType heapType>304 291 NEVER_INLINE void Heap::freeBlock(size_t block) 305 292 { 306 CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 307 308 if (heapType != NumberHeap) { 309 ObjectIterator<heapType> it(heap, block); 310 ObjectIterator<heapType> end(heap, block + 1); 311 for ( ; it != end; ++it) 312 (*it)->~JSCell(); 313 } 314 freeBlock(heap.blocks[block]); 293 ObjectIterator it(m_heap, block); 294 ObjectIterator end(m_heap, block + 1); 295 for ( ; it != end; ++it) 296 (*it)->~JSCell(); 297 freeBlockPtr(m_heap.blocks[block]); 315 298 316 299 // swap with the last block so we compact as we go 317 heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];318 heap.usedBlocks--;319 320 if ( heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks <heap.numBlocks / LOW_WATER_FACTOR) {321 heap.numBlocks =heap.numBlocks / GROWTH_FACTOR;322 heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks,heap.numBlocks * sizeof(CollectorBlock*)));323 } 324 } 325 326 NEVER_INLINE void Heap::freeBlock (CollectorBlock* block)300 m_heap.blocks[block] = m_heap.blocks[m_heap.usedBlocks - 1]; 301 m_heap.usedBlocks--; 302 303 if (m_heap.numBlocks > MIN_ARRAY_SIZE && m_heap.usedBlocks < m_heap.numBlocks / LOW_WATER_FACTOR) { 304 m_heap.numBlocks = m_heap.numBlocks / GROWTH_FACTOR; 305 m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(CollectorBlock*))); 306 } 307 } 308 309 NEVER_INLINE void Heap::freeBlockPtr(CollectorBlock* block) 327 310 { 328 311 #if PLATFORM(DARWIN) … … 345 328 } 346 329 347 template <HeapType heapType>348 330 void Heap::freeBlocks() 349 331 { 350 CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 351 352 while (heap.usedBlocks) 353 freeBlock<heapType>(0); 354 fastFree(heap.blocks); 355 memset(&heap, 0, sizeof(CollectorHeap)); 332 while (m_heap.usedBlocks) 333 freeBlock(0); 334 fastFree(m_heap.blocks); 335 memset(&m_heap, 0, sizeof(CollectorHeap)); 356 336 } 357 337 … … 368 348 // if a large value survives one garbage collection, there is not much point to 369 349 // collecting more frequently as long as it stays alive. 370 // NOTE: we target the primaryHeap unconditionally as JSNumber doesn't modify cost 371 372 if (primaryHeap.extraCost > maxExtraCost && primaryHeap.extraCost > primaryHeap.usedBlocks * BLOCK_SIZE / 2) { 350 351 if (m_heap.extraCost > maxExtraCost && m_heap.extraCost > m_heap.usedBlocks * BLOCK_SIZE / 2) { 373 352 // If the last iteration through the heap deallocated blocks, we need 374 353 // to clean up remaining garbage before marking. Otherwise, the conservative 375 354 // marking mechanism might follow a pointer to unmapped memory. 376 if ( primaryHeap.didShrink)377 sweep <PrimaryHeap>();355 if (m_heap.didShrink) 356 sweep(); 378 357 reset(); 379 358 } 380 primaryHeap.extraCost += cost;381 } 382 383 template <HeapType heapType> ALWAYS_INLINE void* Heap::heapAllocate(size_t s)384 { 385 typedef typename HeapConstants<heapType>::Block Block;386 typedef typename HeapConstants<heapType>::Cell Cell;359 m_heap.extraCost += cost; 360 } 361 362 void* Heap::allocate(size_t s) 363 { 364 typedef HeapConstants::Block Block; 365 typedef HeapConstants::Cell Cell; 387 366 388 CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;389 390 367 ASSERT(JSLock::lockCount() > 0); 391 368 ASSERT(JSLock::currentThreadIsHoldingLock()); 392 ASSERT_UNUSED(s, s <= HeapConstants<heapType>::cellSize); 393 394 ASSERT(heap.operationInProgress == NoOperation); 395 ASSERT(heapType == PrimaryHeap || heap.extraCost == 0); 369 ASSERT_UNUSED(s, s <= HeapConstants::cellSize); 370 371 ASSERT(m_heap.operationInProgress == NoOperation); 396 372 397 373 #if COLLECT_ON_EVERY_ALLOCATION 398 374 collectAllGarbage(); 399 ASSERT( heap.operationInProgress == NoOperation);375 ASSERT(m_heap.operationInProgress == NoOperation); 400 376 #endif 401 377 … … 405 381 406 382 do { 407 ASSERT( heap.nextBlock <heap.usedBlocks);408 Block* block = reinterpret_cast<Block*>( heap.blocks[heap.nextBlock]);383 ASSERT(m_heap.nextBlock < m_heap.usedBlocks); 384 Block* block = reinterpret_cast<Block*>(m_heap.blocks[m_heap.nextBlock]); 409 385 do { 410 ASSERT( heap.nextCell < HeapConstants<heapType>::cellsPerBlock);411 if (!block->marked.get( heap.nextCell >> HeapConstants<heapType>::bitmapShift)) { // Always false for the last cell in the block412 Cell* cell = block->cells + heap.nextCell;413 if (heapType != NumberHeap) { 414 415 416 417 418 } 419 ++ heap.nextCell;386 ASSERT(m_heap.nextCell < HeapConstants::cellsPerBlock); 387 if (!block->marked.get(m_heap.nextCell)) { // Always false for the last cell in the block 388 Cell* cell = block->cells + m_heap.nextCell; 389 390 m_heap.operationInProgress = Allocation; 391 JSCell* imp = reinterpret_cast<JSCell*>(cell); 392 imp->~JSCell(); 393 m_heap.operationInProgress = NoOperation; 394 395 ++m_heap.nextCell; 420 396 return cell; 421 397 } 422 } while (++ heap.nextCell != HeapConstants<heapType>::cellsPerBlock);423 heap.nextCell = 0;424 } while (++ heap.nextBlock !=heap.usedBlocks);398 } while (++m_heap.nextCell != HeapConstants::cellsPerBlock); 399 m_heap.nextCell = 0; 400 } while (++m_heap.nextBlock != m_heap.usedBlocks); 425 401 426 402 // Slow case: reached the end of the heap. Mark live objects and start over. … … 430 406 } 431 407 432 template <HeapType heapType>433 408 void Heap::resizeBlocks() 434 409 { 435 CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 436 437 heap.didShrink = false; 438 439 size_t usedCellCount = markedCells<heapType>(); 410 m_heap.didShrink = false; 411 412 size_t usedCellCount = markedCells(); 440 413 size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount); 441 size_t minBlockCount = (minCellCount + HeapConstants <heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock;414 size_t minBlockCount = (minCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; 442 415 443 416 size_t maxCellCount = 1.25f * minCellCount; 444 size_t maxBlockCount = (maxCellCount + HeapConstants<heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock; 445 446 if (heap.usedBlocks < minBlockCount) 447 growBlocks<heapType>(minBlockCount); 448 else if (heap.usedBlocks > maxBlockCount) 449 shrinkBlocks<heapType>(maxBlockCount); 450 } 451 452 template <HeapType heapType> 417 size_t maxBlockCount = (maxCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; 418 419 if (m_heap.usedBlocks < minBlockCount) 420 growBlocks(minBlockCount); 421 else if (m_heap.usedBlocks > maxBlockCount) 422 shrinkBlocks(maxBlockCount); 423 } 424 453 425 void Heap::growBlocks(size_t neededBlocks) 454 426 { 455 CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 456 ASSERT(heap.usedBlocks < neededBlocks); 457 while (heap.usedBlocks < neededBlocks) 458 allocateBlock<heapType>(); 459 } 460 461 template <HeapType heapType> 427 ASSERT(m_heap.usedBlocks < neededBlocks); 428 while (m_heap.usedBlocks < neededBlocks) 429 allocateBlock(); 430 } 431 462 432 void Heap::shrinkBlocks(size_t neededBlocks) 463 433 { 464 CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 465 ASSERT(heap.usedBlocks > neededBlocks); 434 ASSERT(m_heap.usedBlocks > neededBlocks); 466 435 467 436 // Clear the always-on last bit, so isEmpty() isn't fooled by it. 468 for (size_t i = 0; i < heap.usedBlocks; ++i)469 heap.blocks[i]->marked.clear((HeapConstants<heapType>::cellsPerBlock - 1) >> HeapConstants<heapType>::bitmapShift);470 471 for (size_t i = 0; i != heap.usedBlocks &&heap.usedBlocks != neededBlocks; ) {472 if ( heap.blocks[i]->marked.isEmpty()) {473 freeBlock <heapType>(i);474 heap.didShrink = true;437 for (size_t i = 0; i < m_heap.usedBlocks; ++i) 438 m_heap.blocks[i]->marked.clear(HeapConstants::cellsPerBlock - 1); 439 440 for (size_t i = 0; i != m_heap.usedBlocks && m_heap.usedBlocks != neededBlocks; ) { 441 if (m_heap.blocks[i]->marked.isEmpty()) { 442 freeBlock(i); 443 m_heap.didShrink = true; 475 444 } else 476 445 ++i; … … 478 447 479 448 // Reset the always-on last bit. 480 for (size_t i = 0; i < heap.usedBlocks; ++i) 481 heap.blocks[i]->marked.set((HeapConstants<heapType>::cellsPerBlock - 1) >> HeapConstants<heapType>::bitmapShift); 482 } 483 484 void* Heap::allocate(size_t s) 485 { 486 return heapAllocate<PrimaryHeap>(s); 487 } 488 489 void* Heap::allocateNumber(size_t s) 490 { 491 return heapAllocate<NumberHeap>(s); 449 for (size_t i = 0; i < m_heap.usedBlocks; ++i) 450 m_heap.blocks[i]->marked.set(HeapConstants::cellsPerBlock - 1); 492 451 } 493 452 … … 765 724 return isCellAligned(p) && p; 766 725 } 767 #endif 726 #endif // USE(JSVALUE32) 768 727 769 728 void Heap::markConservatively(MarkStack& markStack, void* start, void* end) … … 782 741 char** e = static_cast<char**>(end); 783 742 784 CollectorBlock** primaryBlocks = primaryHeap.blocks; 785 #if USE(JSVALUE32) 786 CollectorBlock** numberBlocks = numberHeap.blocks; 787 #endif 788 743 CollectorBlock** blocks = m_heap.blocks; 789 744 while (p != e) { 790 745 char* x = *p++; 791 746 if (isPossibleCell(x)) { 792 size_t used PrimaryBlocks;747 size_t usedBlocks; 793 748 uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x); 794 749 xAsBits &= CELL_ALIGN_MASK; … … 800 755 801 756 CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset); 802 #if USE(JSVALUE32) 803 // Mark the the number heap, we can mark these Cells directly to avoid the virtual call cost 804 size_t usedNumberBlocks = numberHeap.usedBlocks; 805 for (size_t block = 0; block < usedNumberBlocks; block++) { 806 if (numberBlocks[block] != blockAddr) 807 continue; 808 Heap::markCell(reinterpret_cast<JSCell*>(xAsBits)); 809 goto endMarkLoop; 810 } 811 #endif 812 813 // Mark the primary heap 814 usedPrimaryBlocks = primaryHeap.usedBlocks; 815 for (size_t block = 0; block < usedPrimaryBlocks; block++) { 816 if (primaryBlocks[block] != blockAddr) 757 usedBlocks = m_heap.usedBlocks; 758 for (size_t block = 0; block < usedBlocks; block++) { 759 if (blocks[block] != blockAddr) 817 760 continue; 818 761 markStack.append(reinterpret_cast<JSCell*>(xAsBits)); 819 762 markStack.drain(); 820 763 } 821 #if USE(JSVALUE32)822 endMarkLoop:823 ;824 #endif825 764 } 826 765 } … … 1064 1003 } 1065 1004 1066 template <HeapType heapType>1067 1005 void Heap::clearMarkBits() 1068 1006 { 1069 CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 1070 for (size_t i = 0; i < heap.usedBlocks; ++i) 1071 clearMarkBits<heapType>(heap.blocks[i]); 1072 } 1073 1074 template <HeapType heapType> 1007 for (size_t i = 0; i < m_heap.usedBlocks; ++i) 1008 clearMarkBits(m_heap.blocks[i]); 1009 } 1010 1075 1011 void Heap::clearMarkBits(CollectorBlock* block) 1076 1012 { 1077 // heapAllocate assumes that the last cell in every block is marked.1013 // allocate assumes that the last cell in every block is marked. 1078 1014 block->marked.clearAll(); 1079 block->marked.set((HeapConstants<heapType>::cellsPerBlock - 1) >> HeapConstants<heapType>::bitmapShift); 1080 } 1081 1082 template <HeapType heapType> 1015 block->marked.set(HeapConstants::cellsPerBlock - 1); 1016 } 1017 1083 1018 size_t Heap::markedCells(size_t startBlock, size_t startCell) const 1084 1019 { 1085 const CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 1086 ASSERT(startBlock <= heap.usedBlocks); 1087 ASSERT(startCell < HeapConstants<heapType>::cellsPerBlock); 1088 1089 if (startBlock >= heap.usedBlocks) 1020 ASSERT(startBlock <= m_heap.usedBlocks); 1021 ASSERT(startCell < HeapConstants::cellsPerBlock); 1022 1023 if (startBlock >= m_heap.usedBlocks) 1090 1024 return 0; 1091 1025 1092 1026 size_t result = 0; 1093 result += heap.blocks[startBlock]->marked.count(startCell);1094 for (size_t i = startBlock + 1; i < heap.usedBlocks; ++i)1095 result += heap.blocks[i]->marked.count();1027 result += m_heap.blocks[startBlock]->marked.count(startCell); 1028 for (size_t i = startBlock + 1; i < m_heap.usedBlocks; ++i) 1029 result += m_heap.blocks[i]->marked.count(); 1096 1030 1097 1031 return result; 1098 1032 } 1099 1033 1100 template <HeapType heapType>1101 1034 void Heap::sweep() 1102 1035 { 1103 ASSERT(heapType != NumberHeap); // The number heap does not contain meaningful destructors. 1104 1105 CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 1106 1107 ASSERT(heap.operationInProgress == NoOperation); 1108 if (heap.operationInProgress != NoOperation) 1036 ASSERT(m_heap.operationInProgress == NoOperation); 1037 if (m_heap.operationInProgress != NoOperation) 1109 1038 CRASH(); 1110 heap.operationInProgress = Collection;1039 m_heap.operationInProgress = Collection; 1111 1040 1112 1041 #if !ENABLE(JSC_ZOMBIES) … … 1114 1043 #endif 1115 1044 1116 DeadObjectIterator <heapType> it(heap, heap.nextBlock,heap.nextCell);1117 DeadObjectIterator <heapType> end(heap,heap.usedBlocks);1045 DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell); 1046 DeadObjectIterator end(m_heap, m_heap.usedBlocks); 1118 1047 for ( ; it != end; ++it) { 1119 1048 JSCell* cell = *it; … … 1132 1061 } 1133 1062 1134 heap.operationInProgress = NoOperation;1063 m_heap.operationInProgress = NoOperation; 1135 1064 } 1136 1065 … … 1144 1073 #endif 1145 1074 1146 ASSERT( (primaryHeap.operationInProgress == NoOperation) & (numberHeap.operationInProgress == NoOperation));1147 if ( !((primaryHeap.operationInProgress == NoOperation) & (numberHeap.operationInProgress == NoOperation)))1075 ASSERT(m_heap.operationInProgress == NoOperation); 1076 if (m_heap.operationInProgress != NoOperation) 1148 1077 CRASH(); 1149 1078 1150 primaryHeap.operationInProgress = Collection; 1151 numberHeap.operationInProgress = Collection; 1079 m_heap.operationInProgress = Collection; 1152 1080 1153 1081 MarkStack& markStack = m_globalData->markStack; 1154 1082 1155 1083 // Reset mark bits. 1156 clearMarkBits<PrimaryHeap>(); 1157 clearMarkBits<NumberHeap>(); 1084 clearMarkBits(); 1158 1085 1159 1086 // Mark stack roots. … … 1178 1105 markStack.compact(); 1179 1106 1180 primaryHeap.operationInProgress = NoOperation; 1181 numberHeap.operationInProgress = NoOperation; 1107 m_heap.operationInProgress = NoOperation; 1182 1108 } 1183 1109 1184 1110 size_t Heap::objectCount() const 1185 1111 { 1186 return objectCount<PrimaryHeap>() + objectCount<NumberHeap>(); 1187 } 1188 1189 template <HeapType heapType> 1190 size_t Heap::objectCount() const 1191 { 1192 const CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 1193 1194 return heap.nextBlock * HeapConstants<heapType>::cellsPerBlock // allocated full blocks 1195 + heap.nextCell // allocated cells in current block 1196 + markedCells<heapType>(heap.nextBlock, heap.nextCell) // marked cells in remainder of heap 1197 - heap.usedBlocks; // 1 cell per block is a dummy sentinel 1198 } 1199 1200 template <HeapType heapType> 1112 return m_heap.nextBlock * HeapConstants::cellsPerBlock // allocated full blocks 1113 + m_heap.nextCell // allocated cells in current block 1114 + markedCells(m_heap.nextBlock, m_heap.nextCell) // marked cells in remainder of m_heap 1115 - m_heap.usedBlocks; // 1 cell per block is a dummy sentinel 1116 } 1117 1201 1118 void Heap::addToStatistics(Heap::Statistics& statistics) const 1202 1119 { 1203 const CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; 1204 1205 statistics.size += heap.usedBlocks * BLOCK_SIZE; 1206 statistics.free += heap.usedBlocks * BLOCK_SIZE - (objectCount<heapType>() * HeapConstants<heapType>::cellSize); 1120 statistics.size += m_heap.usedBlocks * BLOCK_SIZE; 1121 statistics.free += m_heap.usedBlocks * BLOCK_SIZE - (objectCount() * HeapConstants::cellSize); 1207 1122 } 1208 1123 … … 1210 1125 { 1211 1126 Statistics statistics = { 0, 0 }; 1212 addToStatistics<PrimaryHeap>(statistics); 1213 addToStatistics<NumberHeap>(statistics); 1127 addToStatistics(statistics); 1214 1128 return statistics; 1215 1129 } … … 1280 1194 bool Heap::isBusy() 1281 1195 { 1282 return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation);1196 return m_heap.operationInProgress != NoOperation; 1283 1197 } 1284 1198 … … 1291 1205 JAVASCRIPTCORE_GC_MARKED(); 1292 1206 1293 primaryHeap.nextCell = 0; 1294 primaryHeap.nextBlock = 0; 1295 primaryHeap.extraCost = 0; 1207 m_heap.nextCell = 0; 1208 m_heap.nextBlock = 0; 1209 m_heap.nextNumber = 0; 1210 m_heap.extraCost = 0; 1296 1211 #if ENABLE(JSC_ZOMBIES) 1297 sweep<PrimaryHeap>(); 1298 #endif 1299 resizeBlocks<PrimaryHeap>(); 1300 1301 #if USE(JSVALUE32) 1302 numberHeap.nextCell = 0; 1303 numberHeap.nextBlock = 0; 1304 resizeBlocks<NumberHeap>(); 1305 #endif 1212 sweep(); 1213 #endif 1214 resizeBlocks(); 1306 1215 1307 1216 JAVASCRIPTCORE_GC_END(); … … 1315 1224 // to clean up remaining garbage before marking. Otherwise, the conservative 1316 1225 // marking mechanism might follow a pointer to unmapped memory. 1317 if ( primaryHeap.didShrink)1318 sweep <PrimaryHeap>();1226 if (m_heap.didShrink) 1227 sweep(); 1319 1228 1320 1229 markRoots(); … … 1322 1231 JAVASCRIPTCORE_GC_MARKED(); 1323 1232 1324 primaryHeap.nextCell = 0; 1325 primaryHeap.nextBlock = 0; 1326 primaryHeap.extraCost = 0; 1327 sweep<PrimaryHeap>(); 1328 resizeBlocks<PrimaryHeap>(); 1329 1330 #if USE(JSVALUE32) 1331 numberHeap.nextCell = 0; 1332 numberHeap.nextBlock = 0; 1333 resizeBlocks<NumberHeap>(); 1334 #endif 1233 m_heap.nextCell = 0; 1234 m_heap.nextBlock = 0; 1235 m_heap.nextNumber = 0; 1236 m_heap.extraCost = 0; 1237 sweep(); 1238 resizeBlocks(); 1335 1239 1336 1240 JAVASCRIPTCORE_GC_END(); 1337 1241 } 1338 1242 1339 LiveObjectIterator <PrimaryHeap>Heap::primaryHeapBegin()1340 { 1341 return LiveObjectIterator <PrimaryHeap>(primaryHeap, 0);1342 } 1343 1344 LiveObjectIterator <PrimaryHeap>Heap::primaryHeapEnd()1345 { 1346 return LiveObjectIterator <PrimaryHeap>(primaryHeap, primaryHeap.usedBlocks);1243 LiveObjectIterator Heap::primaryHeapBegin() 1244 { 1245 return LiveObjectIterator(m_heap, 0); 1246 } 1247 1248 LiveObjectIterator Heap::primaryHeapEnd() 1249 { 1250 return LiveObjectIterator(m_heap, m_heap.usedBlocks); 1347 1251 } 1348 1252 -
trunk/JavaScriptCore/runtime/Collector.h
r52082 r52176 48 48 49 49 enum OperationInProgress { NoOperation, Allocation, Collection }; 50 enum HeapType { PrimaryHeap, NumberHeap }; 51 52 template <HeapType> class LiveObjectIterator; 50 51 class LiveObjectIterator; 53 52 54 53 struct CollectorHeap { 55 54 size_t nextBlock; 56 55 size_t nextCell; 57 58 56 CollectorBlock** blocks; 57 58 void* nextNumber; 59 59 60 size_t numBlocks; 60 61 size_t usedBlocks; 61 62 62 63 size_t extraCost; 63 64 64 bool didShrink; 65 65 … … 114 114 static bool isNumber(JSCell*); 115 115 116 LiveObjectIterator <PrimaryHeap>primaryHeapBegin();117 LiveObjectIterator <PrimaryHeap>primaryHeapEnd();116 LiveObjectIterator primaryHeapBegin(); 117 LiveObjectIterator primaryHeapEnd(); 118 118 119 119 private: 120 template <HeapType heapType> void* heapAllocate(size_t);121 120 void reset(); 122 void collectRemainingGarbage(); 123 template <HeapType heapType> void sweep(); 121 void sweep(); 124 122 static CollectorBlock* cellBlock(const JSCell*); 125 123 static size_t cellOffset(const JSCell*); … … 129 127 ~Heap(); 130 128 131 template <HeapType heapType>NEVER_INLINE CollectorBlock* allocateBlock();132 template <HeapType heapType>NEVER_INLINE void freeBlock(size_t);133 NEVER_INLINE void freeBlock (CollectorBlock*);134 template <HeapType heapType>void freeBlocks();135 template <HeapType heapType>void resizeBlocks();136 template <HeapType heapType>void growBlocks(size_t neededBlocks);137 template <HeapType heapType>void shrinkBlocks(size_t neededBlocks);138 template <HeapType heapType>void clearMarkBits();139 template <HeapType heapType>void clearMarkBits(CollectorBlock*);140 template <HeapType heapType>size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const;129 NEVER_INLINE CollectorBlock* allocateBlock(); 130 NEVER_INLINE void freeBlock(size_t); 131 NEVER_INLINE void freeBlockPtr(CollectorBlock*); 132 void freeBlocks(); 133 void resizeBlocks(); 134 void growBlocks(size_t neededBlocks); 135 void shrinkBlocks(size_t neededBlocks); 136 void clearMarkBits(); 137 void clearMarkBits(CollectorBlock*); 138 size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const; 141 139 142 140 void recordExtraCost(size_t); 143 141 144 template <HeapType heapType> void addToStatistics(Statistics&) const; 145 template <HeapType heapType> size_t objectCount() const; 142 void addToStatistics(Statistics&) const; 146 143 147 144 void markRoots(); … … 154 151 typedef HashCountedSet<JSCell*> ProtectCountSet; 155 152 156 CollectorHeap primaryHeap; 157 CollectorHeap numberHeap; 153 CollectorHeap m_heap; 158 154 159 155 ProtectCountSet m_protectedValues; … … 201 197 const size_t CELL_MASK = CELL_SIZE - 1; 202 198 const size_t CELL_ALIGN_MASK = ~CELL_MASK; 203 const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*) - sizeof(HeapType)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells.199 const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells. 204 200 205 const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK;206 201 const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8; 207 202 const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t); … … 237 232 }; 238 233 239 struct SmallCollectorCell {240 double memory[CELL_ARRAY_LENGTH / 2];241 };242 243 234 class CollectorBlock { 244 235 public: … … 246 237 CollectorBitmap marked; 247 238 Heap* heap; 248 HeapType type; 249 }; 250 251 class SmallCellCollectorBlock { 252 public: 253 SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK]; 254 CollectorBitmap marked; 255 Heap* heap; 256 HeapType type; 257 }; 258 259 template <HeapType heapType> struct HeapConstants; 260 261 template <> struct HeapConstants<PrimaryHeap> { 239 }; 240 241 struct HeapConstants { 262 242 static const size_t cellSize = CELL_SIZE; 263 243 static const size_t cellsPerBlock = CELLS_PER_BLOCK; 264 static const size_t bitmapShift = 0;265 244 typedef CollectorCell Cell; 266 245 typedef CollectorBlock Block; 267 246 }; 268 247 269 template <> struct HeapConstants<NumberHeap> {270 static const size_t cellSize = SMALL_CELL_SIZE;271 static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK;272 static const size_t bitmapShift = 1;273 typedef SmallCollectorCell Cell;274 typedef SmallCellCollectorBlock Block;275 };276 277 248 inline CollectorBlock* Heap::cellBlock(const JSCell* cell) 278 249 { 279 250 return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK); 280 }281 282 inline bool Heap::isNumber(JSCell* cell)283 {284 return Heap::cellBlock(cell)->type == NumberHeap;285 251 } 286 252 … … 305 271 recordExtraCost(cost); 306 272 } 273 274 inline void* Heap::allocateNumber(size_t s) 275 { 276 if (void* result = m_heap.nextNumber) { 277 m_heap.nextNumber = 0; 278 return result; 279 } 280 281 void* result = allocate(s); 282 m_heap.nextNumber = static_cast<char*>(result) + (CELL_SIZE / 2); 283 return result; 284 } 307 285 308 286 } // namespace JSC -
trunk/JavaScriptCore/runtime/CollectorHeapIterator.h
r52082 r52176 46 46 }; 47 47 48 template <HeapType heapType>49 48 class LiveObjectIterator : public CollectorHeapIterator { 50 49 public: 51 50 LiveObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0); 52 LiveObjectIterator <heapType>& operator++();51 LiveObjectIterator& operator++(); 53 52 }; 54 53 55 template <HeapType heapType>56 54 class DeadObjectIterator : public CollectorHeapIterator { 57 55 public: 58 56 DeadObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0); 59 DeadObjectIterator <heapType>& operator++();57 DeadObjectIterator& operator++(); 60 58 }; 61 59 62 template <HeapType heapType>63 60 class ObjectIterator : public CollectorHeapIterator { 64 61 public: 65 62 ObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0); 66 ObjectIterator <heapType>& operator++();63 ObjectIterator& operator++(); 67 64 }; 68 65 … … 93 90 } 94 91 95 template <HeapType heapType> 96 inline LiveObjectIterator<heapType>::LiveObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) 92 inline LiveObjectIterator::LiveObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) 97 93 : CollectorHeapIterator(heap, startBlock, startCell - 1) 98 94 { … … 100 96 } 101 97 102 template <HeapType heapType> 103 inline LiveObjectIterator<heapType>& LiveObjectIterator<heapType>::operator++() 98 inline LiveObjectIterator& LiveObjectIterator::operator++() 104 99 { 105 100 if (m_block < m_heap.nextBlock || m_cell < m_heap.nextCell) { 106 advance(HeapConstants <heapType>::cellsPerBlock);101 advance(HeapConstants::cellsPerBlock); 107 102 return *this; 108 103 } 109 104 110 105 do { 111 advance(HeapConstants <heapType>::cellsPerBlock);106 advance(HeapConstants::cellsPerBlock); 112 107 } while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell)); 113 108 return *this; 114 109 } 115 110 116 template <HeapType heapType> 117 inline DeadObjectIterator<heapType>::DeadObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) 111 inline DeadObjectIterator::DeadObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) 118 112 : CollectorHeapIterator(heap, startBlock, startCell - 1) 119 113 { … … 121 115 } 122 116 123 template <HeapType heapType> 124 inline DeadObjectIterator<heapType>& DeadObjectIterator<heapType>::operator++() 117 inline DeadObjectIterator& DeadObjectIterator::operator++() 125 118 { 126 119 do { 127 advance(HeapConstants <heapType>::cellsPerBlock);120 advance(HeapConstants::cellsPerBlock); 128 121 ASSERT(m_block > m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell >= m_heap.nextCell)); 129 122 } while (m_block < m_heap.usedBlocks && m_heap.blocks[m_block]->marked.get(m_cell)); … … 131 124 } 132 125 133 template <HeapType heapType> 134 inline ObjectIterator<heapType>::ObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) 126 inline ObjectIterator::ObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) 135 127 : CollectorHeapIterator(heap, startBlock, startCell - 1) 136 128 { … … 138 130 } 139 131 140 template <HeapType heapType> 141 inline ObjectIterator<heapType>& ObjectIterator<heapType>::operator++() 132 inline ObjectIterator& ObjectIterator::operator++() 142 133 { 143 advance(HeapConstants <heapType>::cellsPerBlock);134 advance(HeapConstants::cellsPerBlock); 144 135 return *this; 145 136 } -
trunk/JavaScriptCore/runtime/JSCell.h
r52082 r52176 134 134 inline bool JSCell::isNumber() const 135 135 { 136 return Heap::isNumber(const_cast<JSCell*>(this));136 return m_structure->typeInfo().type() == NumberType; 137 137 } 138 138 #endif
Note:
See TracChangeset
for help on using the changeset viewer.