Changeset 10179 in webkit for trunk/JavaScriptCore
- Timestamp:
- Aug 14, 2005, 9:17:11 AM (20 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r10178 r10179 1 2005-08-14 Darin Adler <[email protected]> 2 3 Reviewed by Maciej. 4 5 - fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=4416 6 speed up JavaScript with some improvements to the garbage collector 7 8 seems to give about 2% on iBench JavaScript 9 10 * kjs/collector.cpp: 11 (KJS::Collector::allocate): Use local variables to shadow globals instead of repeatedly 12 going at global variables. Tighten up loop implementations to make the common case fast. 13 (KJS::Collector::markStackObjectsConservatively): Use local variables to shadow globals. 14 Used a goto to eliminate a boolean since it was showing up in the profile. 15 (KJS::Collector::markProtectedObjects): Iterate through the table using pointer rather 16 than an index since the profile showed that generating better code. 17 (KJS::Collector::collect): Added a special case for blocks where all cells are used, 18 Use local variables to shadow globals. Eliminated a boolean by computing it another 19 way (checking to see if the number of live objects changed). Also used local variables 20 to shadow fields in the current cell when sweeping. 21 (KJS::Collector::numReferencedObjects): Use AllocatedValueImp instead of ValueImp 22 in one place -- means we get faster versions of various functions that don't worry 23 about SimpleNumber. 24 (KJS::className): Ditto. 25 (KJS::Collector::rootObjectClasses): Ditto. 26 1 27 2005-08-14 Darin Adler <[email protected]> 2 28 -
trunk/JavaScriptCore/kjs/collector.cpp
r10084 r10179 105 105 if (s > static_cast<size_t>(CELL_SIZE)) { 106 106 // oversize allocator 107 if (heap.usedOversizeCells == heap.numOversizeCells) { 108 heap.numOversizeCells = max(MIN_ARRAY_SIZE, heap.numOversizeCells * GROWTH_FACTOR); 109 heap.oversizeCells = (CollectorCell **)kjs_fast_realloc(heap.oversizeCells, heap.numOversizeCells * sizeof(CollectorCell *)); 107 108 int usedOversizeCells = heap.usedOversizeCells; 109 int numOversizeCells = heap.numOversizeCells; 110 111 if (usedOversizeCells == numOversizeCells) { 112 numOversizeCells = max(MIN_ARRAY_SIZE, numOversizeCells * GROWTH_FACTOR); 113 heap.numOversizeCells = numOversizeCells; 114 heap.oversizeCells = static_cast<CollectorCell **>(kjs_fast_realloc(heap.oversizeCells, numOversizeCells * sizeof(CollectorCell *))); 110 115 } 111 116 112 117 void *newCell = kjs_fast_malloc(s); 113 heap.oversizeCells[ heap.usedOversizeCells] = (CollectorCell *)newCell;114 heap.usedOversizeCells ++;118 heap.oversizeCells[usedOversizeCells] = static_cast<CollectorCell *>(newCell); 119 heap.usedOversizeCells = usedOversizeCells + 1; 115 120 heap.numLiveObjects = numLiveObjects + 1; 116 121 … … 120 125 // slab allocator 121 126 122 CollectorBlock *targetBlock = NULL; 123 124 int i; 125 for (i = heap.firstBlockWithPossibleSpace; i < heap.usedBlocks; i++) { 126 if (heap.blocks[i]->usedCells < CELLS_PER_BLOCK) { 127 int usedBlocks = heap.usedBlocks; 128 129 int i = heap.firstBlockWithPossibleSpace; 130 CollectorBlock *targetBlock; 131 int targetBlockUsedCells; 132 if (i != usedBlocks) { 133 targetBlock = heap.blocks[i]; 134 targetBlockUsedCells = targetBlock->usedCells; 135 assert(targetBlockUsedCells <= CELLS_PER_BLOCK); 136 while (targetBlockUsedCells == CELLS_PER_BLOCK) { 137 if (++i == usedBlocks) 138 goto allocateNewBlock; 127 139 targetBlock = heap.blocks[i]; 128 break; 129 } 130 } 131 132 heap.firstBlockWithPossibleSpace = i; 133 134 if (targetBlock == NULL) { 140 targetBlockUsedCells = targetBlock->usedCells; 141 assert(targetBlockUsedCells <= CELLS_PER_BLOCK); 142 } 143 heap.firstBlockWithPossibleSpace = i; 144 } else { 145 allocateNewBlock: 135 146 // didn't find one, need to allocate a new block 136 137 if (heap.usedBlocks == heap.numBlocks) { 138 heap.numBlocks = max(MIN_ARRAY_SIZE, heap.numBlocks * GROWTH_FACTOR); 139 heap.blocks = (CollectorBlock **)kjs_fast_realloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock *)); 140 } 141 142 targetBlock = (CollectorBlock *)kjs_fast_calloc(1, sizeof(CollectorBlock)); 147 148 int numBlocks = heap.numBlocks; 149 if (usedBlocks == heap.numBlocks) { 150 numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); 151 heap.numBlocks = numBlocks; 152 heap.blocks = static_cast<CollectorBlock **>(kjs_fast_realloc(heap.blocks, numBlocks * sizeof(CollectorBlock *))); 153 } 154 155 targetBlock = static_cast<CollectorBlock *>(kjs_fast_calloc(1, sizeof(CollectorBlock))); 143 156 targetBlock->freeList = targetBlock->cells; 144 heap.blocks[heap.usedBlocks] = targetBlock; 145 heap.usedBlocks++; 157 targetBlockUsedCells = 0; 158 heap.blocks[usedBlocks] = targetBlock; 159 heap.usedBlocks = usedBlocks + 1; 160 heap.firstBlockWithPossibleSpace = usedBlocks; 146 161 } 147 162 … … 153 168 targetBlock->freeList = reinterpret_cast<CollectorCell *>(reinterpret_cast<char *>(newCell + 1) + newCell->u.freeCell.next); 154 169 155 targetBlock->usedCells ++;170 targetBlock->usedCells = targetBlockUsedCells + 1; 156 171 heap.numLiveObjects = numLiveObjects + 1; 157 172 … … 228 243 char **e = (char **)end; 229 244 245 int usedBlocks = heap.usedBlocks; 246 CollectorBlock **blocks = heap.blocks; 247 int usedOversizeCells = heap.usedOversizeCells; 248 CollectorCell **oversizeCells = heap.oversizeCells; 249 250 const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1); 251 230 252 while (p != e) { 231 253 char *x = *p++; 232 254 if (IS_CELL_ALIGNED(x) && x) { 233 bool good = false; 234 for (int block = 0; block < heap.usedBlocks; block++) { 235 size_t offset = x - (char *)heap.blocks[block]; 236 const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1); 237 if (offset <= lastCellOffset && offset % sizeof(CollectorCell) == 0) { 238 good = true; 239 break; 240 } 241 } 242 243 if (!good) { 244 int n = heap.usedOversizeCells; 245 for (int i = 0; i != n; i++) { 246 if (x == (char *)heap.oversizeCells[i]) { 247 good = true; 248 break; 249 } 250 } 251 } 252 253 if (good && ((CollectorCell *)x)->u.freeCell.zeroIfFree != 0) { 254 AllocatedValueImp *imp = (AllocatedValueImp *)x; 255 if (!imp->marked()) 256 imp->mark(); 255 for (int block = 0; block < usedBlocks; block++) { 256 size_t offset = x - reinterpret_cast<char *>(blocks[block]); 257 if (offset <= lastCellOffset && offset % sizeof(CollectorCell) == 0) 258 goto gotGoodPointer; 259 } 260 for (int i = 0; i != usedOversizeCells; i++) 261 if (x == reinterpret_cast<char *>(oversizeCells[i])) 262 goto gotGoodPointer; 263 continue; 264 265 gotGoodPointer: 266 if (((CollectorCell *)x)->u.freeCell.zeroIfFree != 0) { 267 AllocatedValueImp *imp = reinterpret_cast<AllocatedValueImp *>(x); 268 if (!imp->marked()) 269 imp->mark(); 257 270 } 258 271 } … … 324 337 void Collector::markProtectedObjects() 325 338 { 326 int size = ProtectedValues::_tableSize; 327 ProtectedValues::KeyValue *table = ProtectedValues::_table; 328 for (int i = 0; i < size; i++) { 329 ValueImp *val = table[i].key; 339 typedef ProtectedValues::KeyValue Entry; 340 Entry *table = ProtectedValues::_table; 341 Entry *end = table + ProtectedValues::_tableSize; 342 for (Entry *entry = table; entry != end; ++entry) { 343 AllocatedValueImp *val = entry->key; 330 344 if (val && !val->marked()) { 331 345 val->mark(); … … 337 351 { 338 352 assert(Interpreter::lockCount() > 0); 339 340 bool deleted = false;341 353 342 354 if (InterpreterImp::s_hook) { … … 363 375 CollectorBlock *curBlock = heap.blocks[block]; 364 376 365 int minimumCellsToProcess = curBlock->usedCells; 366 367 for (int i = 0; i < CELLS_PER_BLOCK; i++) { 368 if (minimumCellsToProcess < i) { 369 goto skip_block_sweep; 370 } 371 372 CollectorCell *cell = curBlock->cells + i; 373 AllocatedValueImp *imp = reinterpret_cast<AllocatedValueImp *>(cell); 374 375 if (cell->u.freeCell.zeroIfFree != 0) { 376 if (!imp->m_marked) 377 { 378 //fprintf(stderr, "Collector::deleting AllocatedValueImp %p (%s)\n", imp, className(imp)); 379 // emulate destructing part of 'operator delete()' 380 imp->~AllocatedValueImp(); 381 curBlock->usedCells--; 382 numLiveObjects--; 383 deleted = true; 384 385 // put it on the free list 386 cell->u.freeCell.zeroIfFree = 0; 387 cell->u.freeCell.next = reinterpret_cast<char *>(curBlock->freeList) - reinterpret_cast<char *>(cell + 1); 388 curBlock->freeList = cell; 389 390 } else { 391 imp->m_marked = false; 392 } 393 } else { 394 minimumCellsToProcess++; 395 } 396 } 397 398 skip_block_sweep: 399 400 if (heap.blocks[block]->usedCells == 0) { 377 int usedCells = curBlock->usedCells; 378 CollectorCell *freeList = curBlock->freeList; 379 380 if (usedCells == CELLS_PER_BLOCK) { 381 // special case with a block where all cells are used -- testing indicates this happens often 382 for (int i = 0; i < CELLS_PER_BLOCK; i++) { 383 CollectorCell *cell = curBlock->cells + i; 384 AllocatedValueImp *imp = reinterpret_cast<AllocatedValueImp *>(cell); 385 if (imp->m_marked) { 386 imp->m_marked = false; 387 } else { 388 imp->~AllocatedValueImp(); 389 --usedCells; 390 --numLiveObjects; 391 392 // put cell on the free list 393 cell->u.freeCell.zeroIfFree = 0; 394 cell->u.freeCell.next = reinterpret_cast<char *>(freeList) - reinterpret_cast<char *>(cell + 1); 395 freeList = cell; 396 } 397 } 398 } else { 399 int minimumCellsToProcess = usedCells; 400 for (int i = 0; i < minimumCellsToProcess; i++) { 401 CollectorCell *cell = curBlock->cells + i; 402 if (cell->u.freeCell.zeroIfFree == 0) { 403 ++minimumCellsToProcess; 404 } else { 405 AllocatedValueImp *imp = reinterpret_cast<AllocatedValueImp *>(cell); 406 if (imp->m_marked) { 407 imp->m_marked = false; 408 } else { 409 imp->~AllocatedValueImp(); 410 --usedCells; 411 --numLiveObjects; 412 413 // put cell on the free list 414 cell->u.freeCell.zeroIfFree = 0; 415 cell->u.freeCell.next = reinterpret_cast<char *>(freeList) - reinterpret_cast<char *>(cell + 1); 416 freeList = cell; 417 } 418 } 419 } 420 } 421 422 curBlock->usedCells = usedCells; 423 curBlock->freeList = freeList; 424 425 if (usedCells == 0) { 401 426 emptyBlocks++; 402 427 if (emptyBlocks > SPARE_EMPTY_BLOCKS) { 403 428 #if !DEBUG_COLLECTOR 404 kjs_fast_free(heap.blocks[block]);429 kjs_fast_free(curBlock); 405 430 #endif 406 407 408 409 410 411 412 413 414 415 } 416 } 417 } 418 419 if ( deleted) {431 // swap with the last block so we compact as we go 432 heap.blocks[block] = heap.blocks[heap.usedBlocks - 1]; 433 heap.usedBlocks--; 434 block--; // Don't move forward a step in this case 435 436 if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) { 437 heap.numBlocks = heap.numBlocks / GROWTH_FACTOR; 438 heap.blocks = (CollectorBlock **)kjs_fast_realloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock *)); 439 } 440 } 441 } 442 } 443 444 if (heap.numLiveObjects != numLiveObjects) 420 445 heap.firstBlockWithPossibleSpace = 0; 421 }422 446 423 447 int cell = 0; … … 430 454 heap.oversizeCells[cell]->u.freeCell.zeroIfFree = 0; 431 455 #else 432 kjs_fast_free( (void *)imp);456 kjs_fast_free(imp); 433 457 #endif 434 458 … … 437 461 438 462 heap.usedOversizeCells--; 439 deleted = true;440 463 numLiveObjects--; 441 464 442 465 if (heap.numOversizeCells > MIN_ARRAY_SIZE && heap.usedOversizeCells < heap.numOversizeCells / LOW_WATER_FACTOR) { 443 heap.numOversizeCells = heap.numOversizeCells / GROWTH_FACTOR; 444 heap.oversizeCells = (CollectorCell **)kjs_fast_realloc(heap.oversizeCells, heap.numOversizeCells * sizeof(CollectorCell *)); 445 } 446 466 heap.numOversizeCells = heap.numOversizeCells / GROWTH_FACTOR; 467 heap.oversizeCells = (CollectorCell **)kjs_fast_realloc(heap.oversizeCells, heap.numOversizeCells * sizeof(CollectorCell *)); 468 } 447 469 } else { 448 470 imp->m_marked = false; … … 451 473 } 452 474 475 bool deleted = heap.numLiveObjects != numLiveObjects; 476 453 477 heap.numLiveObjects = numLiveObjects; 454 478 heap.numLiveObjectsAtLastCollect = numLiveObjects; … … 495 519 ProtectedValues::KeyValue *table = ProtectedValues::_table; 496 520 for (int i = 0; i < size; i++) { 497 ValueImp *val = table[i].key;521 AllocatedValueImp *val = table[i].key; 498 522 if (val) { 499 523 ++count; … … 506 530 #if APPLE_CHANGES 507 531 508 static const char *className( ValueImp *val)532 static const char *className(AllocatedValueImp *val) 509 533 { 510 534 const char *name = "???"; … … 543 567 ProtectedValues::KeyValue *table = ProtectedValues::_table; 544 568 for (int i = 0; i < size; i++) { 545 ValueImp *val = table[i].key;569 AllocatedValueImp *val = table[i].key; 546 570 if (val) { 547 571 CFStringRef name = CFStringCreateWithCString(NULL, className(val), kCFStringEncodingASCII);
Note:
See TracChangeset
for help on using the changeset viewer.