Ignore:
Timestamp:
Nov 23, 2002, 4:04:08 PM (23 years ago)
Author:
mjs
Message:

Numerous collector changes for a net gain of 3% on JS ibench:

  • Replaced per-block bitmap with free list.
  • Increased number of empty blocks kept around to 2.
  • Doubled block size.
  • When scanning heap in collector, skip scanning the rest of a block as soon as we see as many live cells as the the number of used cells it had originally.

Also the following collector changes unrelated to performance:

  • Made constants const int' instead of static const int'.
  • Miscellaneous code cleanup.
  • kjs/collector.cpp:
  • Added debugging mode enabled by defining DEBUG_GC which asserts when a destroyed ValueImp
  • kjs/internal.cpp: (ContextImp::mark):
  • kjs/value.cpp: (Value::Value):
  • kjs/value.h:
  • kjs/config.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/collector.cpp

    r2843 r2845  
    22/*
    33 *  This file is part of the KDE libraries
    4  *  Copyright (C) 2002 Apple Computer, Inc.
     4 *  Copyright (C) 2002 Apple Computer, Inc
    55 *
    66 *  This library is free software; you can redistribute it and/or
     
    3030#endif
    3131
     32#include <collector.h>
     33#include <value.h>
     34#include <internal.h>
     35
    3236namespace KJS {
    3337
    3438// tunable parameters
    35 static const int CELL_SIZE = 56;
    36 static const int BLOCK_SIZE = (4 * 4096);
    37 static const int SPARE_EMPTY_BLOCKS = 1;
    38 static const int MIN_ARRAY_SIZE = 14;
    39 static const int GROWTH_FACTOR = 2;
    40 static const int LOW_WATER_FACTOR = 4;
     39const int MINIMUM_CELL_SIZE = 56;
     40const int BLOCK_SIZE = (8 * 4096);
     41const int SPARE_EMPTY_BLOCKS = 2;
     42const int MIN_ARRAY_SIZE = 14;
     43const int GROWTH_FACTOR = 2;
     44const int LOW_WATER_FACTOR = 4;
     45const int ALLOCATIONS_PER_COLLECTION = 1000;
    4146
    4247// derived constants
    43 static const int WORD_SIZE = sizeof(uint32_t);
    44 static const int BITS_PER_WORD = WORD_SIZE * 8;
    45 static const uint32_t ALL_BITS_ON = 0xffffffff;
    46 static const int CELLS_PER_BLOCK = ((BLOCK_SIZE * 8 - 32) / (CELL_SIZE * 8 + 1));
    47 static const int BITMAP_SIZE = (CELLS_PER_BLOCK / BITS_PER_WORD) + (CELLS_PER_BLOCK % BITS_PER_WORD != 0 ? 1 : 0);
     48const int CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
     49const int CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
     50const int CELLS_PER_BLOCK = ((BLOCK_SIZE * 8 - sizeof(int32_t) * 8 - sizeof(void *) * 8) / (CELL_SIZE * 8));
     51
    4852
    4953
    5054struct CollectorCell {
    51   char memory[CELL_SIZE];
     55  union {
     56    double memory[CELL_ARRAY_LENGTH];
     57    struct {
     58      void *zeroIfFree;
     59      CollectorCell *next;
     60    } freeCell;
     61  } u;
    5262};
    5363
    54 static const int ALLOCATIONS_PER_COLLECTION = 1000;
    5564
    5665struct CollectorBlock {
    57   CollectorBlock() : usedCells(0) { memset(bitmap, 0, BITMAP_SIZE * WORD_SIZE); }
    58  
    59   uint32_t bitmap[BITMAP_SIZE];
     66  CollectorCell cells[CELLS_PER_BLOCK];
    6067  int32_t usedCells;
    61   CollectorCell cells[CELLS_PER_BLOCK];
     68  CollectorCell *freeList;
    6269};
    6370
     
    6673  int numBlocks;
    6774  int usedBlocks;
     75  int firstBlockWithPossibleSpace;
    6876 
    6977  CollectorCell **oversizeCells;
     
    7583};
    7684
    77 static CollectorHeap heap = {NULL, 0, 0, NULL, 0, 0, 0, 0};
     85static CollectorHeap heap = {NULL, 0, 0, 0, NULL, 0, 0, 0, 0};
    7886
    7987bool Collector::memoryFull = false;
    80 
    8188
    8289void* Collector::allocate(size_t s)
     
    8693 
    8794  // collect if needed
    88   if (++heap.numAllocationsSinceLastCollect >= ALLOCATIONS_PER_COLLECTION)
     95  if (++heap.numAllocationsSinceLastCollect >= ALLOCATIONS_PER_COLLECTION) {
    8996    collect();
     97  }
    9098 
    9199  if (s > (unsigned)CELL_SIZE) {
     
    109117  CollectorBlock *targetBlock = NULL;
    110118 
    111   // try to find free space in an existing block
    112   for (int i = 0; i < heap.usedBlocks; i++) {
     119  int i;
     120  for (i = heap.firstBlockWithPossibleSpace; i < heap.usedBlocks; i++) {
    113121    if (heap.blocks[i]->usedCells < CELLS_PER_BLOCK) {
    114122      targetBlock = heap.blocks[i];
     
    116124    }
    117125  }
     126
     127  heap.firstBlockWithPossibleSpace = i;
    118128 
    119129  if (targetBlock == NULL) {
     
    125135    }
    126136   
    127     targetBlock = new CollectorBlock();
     137    targetBlock = (CollectorBlock *)calloc(1, sizeof(CollectorBlock));
     138    targetBlock->freeList = targetBlock->cells;
    128139    heap.blocks[heap.usedBlocks] = targetBlock;
    129140    heap.usedBlocks++;
    130141  }
    131142 
    132   // find a free spot in the block
    133   for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) {
    134     uint32_t word = targetBlock->bitmap[wordInBitmap];
    135     if (word == ALL_BITS_ON) {
    136       continue;
    137     }
    138     for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) {
    139       if ((word & (1 << bitInWord)) == 0) {
    140         int cellPos = BITS_PER_WORD * wordInBitmap + bitInWord;
    141         if (cellPos < CELLS_PER_BLOCK) {
    142           targetBlock->bitmap[wordInBitmap] |= (1 << bitInWord);
    143           targetBlock->usedCells++;
    144           heap.numLiveObjects++;
    145 
    146           ((ValueImp *)(targetBlock->cells + cellPos))->_flags = 0;
    147           return (void *)(targetBlock->cells + cellPos);
    148         }
    149       }
    150     }
    151   }
    152   // unreachable, if the free count wasn't 0 there has to be a free
    153   // cell in the block
    154   assert(false);
    155 
    156   return false;
     143  // find a free spot in the block and detach it from the free list
     144  CollectorCell *newCell = targetBlock->freeList;
     145
     146  if (newCell->u.freeCell.next != NULL) {
     147    targetBlock->freeList = newCell->u.freeCell.next;
     148  } else if (targetBlock->usedCells == (CELLS_PER_BLOCK - 1)) {
     149    // last cell in this block
     150    targetBlock->freeList = NULL;
     151  } else {
     152    // all next pointers are initially 0, meaning "next cell"
     153    targetBlock->freeList = newCell + 1;
     154  }
     155
     156  targetBlock->usedCells++;
     157  heap.numLiveObjects++;
     158
     159  ((ValueImp *)(newCell))->_flags = 0;
     160  return (void *)(newCell);
    157161}
    158162
     
    174178  // mark any other objects that we wouldn't delete anyway
    175179  for (int block = 0; block < heap.usedBlocks; block++) {
    176     for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) {
    177       uint32_t word = heap.blocks[block]->bitmap[wordInBitmap];
    178       for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) {
    179         ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord);
     180
     181    int minimumCellsToProcess = heap.blocks[block]->usedCells;
     182    CollectorBlock *curBlock = heap.blocks[block];
     183
     184    for (int cell = 0; cell < CELLS_PER_BLOCK; cell++) {
     185      if (minimumCellsToProcess < cell) {
     186        goto skip_block_mark;
     187      }
    180188       
    181         if ((word & (1 << bitInWord)) &&
    182             (imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
     189      ValueImp *imp = (ValueImp *)(curBlock->cells + cell);
     190
     191      if (((CollectorCell *)imp)->u.freeCell.zeroIfFree != 0) {
     192       
     193        if ((imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
    183194            ((imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount != 0)) {
    184195          imp->mark();
    185196        }
    186       }
    187     }
     197      } else {
     198        minimumCellsToProcess++;
     199      }
     200    }
     201  skip_block_mark: ;
    188202  }
    189203 
     
    201215
    202216  for (int block = 0; block < heap.usedBlocks; block++) {
    203     for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) {
    204       uint32_t word = heap.blocks[block]->bitmap[wordInBitmap];
    205       for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) {
    206        
    207         if (word & (1 << bitInWord)) {
    208         ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord);
    209           if (!imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) {
    210             //fprintf( stderr, "Collector::deleting ValueImp %p (%s)\n", (void*)imp, typeid(*imp).name());
    211             // emulate destructing part of 'operator delete()'
    212             imp->~ValueImp();
    213             heap.blocks[block]->bitmap[wordInBitmap] &= ~(1 << bitInWord);
    214             heap.blocks[block]->usedCells--;
    215             heap.numLiveObjects--;
    216             deleted = true;
    217           } else {
    218             imp->_flags &= ~ValueImp::VI_MARKED;
    219           }
     217    CollectorBlock *curBlock = heap.blocks[block];
     218
     219    int minimumCellsToProcess = curBlock->usedCells;
     220
     221    for (int cell = 0; cell < CELLS_PER_BLOCK; cell++) {
     222      if (minimumCellsToProcess < cell) {
     223        goto skip_block_sweep;
     224      }
     225
     226      ValueImp *imp = (ValueImp *)(curBlock->cells + cell);
     227
     228      if (((CollectorCell *)imp)->u.freeCell.zeroIfFree != 0) {
     229        if (!imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) {
     230          //fprintf( stderr, "Collector::deleting ValueImp %p (%s)\n", (void*)imp, typeid(*imp).name());
     231          // emulate destructing part of 'operator delete()'
     232          imp->~ValueImp();
     233          curBlock->usedCells--;
     234          heap.numLiveObjects--;
     235          deleted = true;
     236
     237          // put it on the free list
     238          ((CollectorCell *)imp)->u.freeCell.zeroIfFree = 0;
     239          ((CollectorCell *)imp)->u.freeCell.next = curBlock->freeList;
     240          curBlock->freeList = (CollectorCell *)imp;
     241
     242        } else {
     243          imp->_flags &= ~ValueImp::VI_MARKED;
    220244        }
    221       }
    222     }
     245      } else {
     246        minimumCellsToProcess++;
     247      }
     248    }
     249
     250  skip_block_sweep:
    223251
    224252    if (heap.blocks[block]->usedCells == 0) {
     
    240268  }
    241269
     270  if (deleted) {
     271    heap.firstBlockWithPossibleSpace = 0;
     272  }
    242273 
    243274  int cell = 0;
     
    269300  }
    270301 
    271   // possibly free some completely empty collector blocks ?
    272   // compact array of collector blocks
    273  
    274302  heap.numAllocationsSinceLastCollect = 0;
    275303 
     
    309337  int count = 0;
    310338  for (int block = 0; block < heap.usedBlocks; block++) {
    311     for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) {
    312       uint32_t word = heap.blocks[block]->bitmap[wordInBitmap];
    313       for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) {
    314         ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord);
    315        
    316         if ((word & (1 << bitInWord)) &&
    317             (imp->_flags & ValueImp::VI_GCALLOWED) == 0) {
    318           ++count;
    319         }
     339    CollectorBlock *curBlock = heap.blocks[block];
     340
     341    for (int cell = 0; cell < CELLS_PER_BLOCK; cell++) {
     342      ValueImp *imp = (ValueImp *)(curBlock->cells + cell);
     343     
     344      if (((CollectorCell *)imp)->u.freeCell.zeroIfFree != 0 &&
     345          (imp->_flags & ValueImp::VI_GCALLOWED) == 0) {
     346        ++count;
    320347      }
    321348    }
     
    324351  for (int cell = 0; cell < heap.usedOversizeCells; cell++) {
    325352    ValueImp *imp = (ValueImp *)heap.oversizeCells[cell];
    326       if ((imp->_flags & ValueImp::VI_GCALLOWED) == 0) {
    327         ++count;
    328       }
     353    if ((imp->_flags & ValueImp::VI_GCALLOWED) == 0) {
     354      ++count;
     355    }
    329356  }
    330357
     
    336363  int count = 0;
    337364  for (int block = 0; block < heap.usedBlocks; block++) {
    338     for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) {
    339       uint32_t word = heap.blocks[block]->bitmap[wordInBitmap];
    340       for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) {
    341         ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord);
    342        
    343         if ((word & (1 << bitInWord)) &&
    344             imp->refcount != 0) {
    345           ++count;
    346         }
     365    CollectorBlock *curBlock = heap.blocks[block];
     366
     367    for (int cell = 0; cell < CELLS_PER_BLOCK; cell++) {
     368      ValueImp *imp = (ValueImp *)(curBlock->cells + cell);
     369     
     370      if (((CollectorCell *)imp)->u.freeCell.zeroIfFree != 0 &&
     371          imp->refcount != 0) {
     372        ++count;
    347373      }
    348374    }
     
    362388{
    363389  CFMutableSetRef classes = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
    364 
     390 
    365391  for (int block = 0; block < heap.usedBlocks; block++) {
    366     for (int wordInBitmap = 0; wordInBitmap < BITMAP_SIZE; wordInBitmap++) {
    367       uint32_t word = heap.blocks[block]->bitmap[wordInBitmap];
    368       for (int bitInWord = 0; bitInWord < BITS_PER_WORD; bitInWord++) {
    369         ValueImp *imp = (ValueImp *)(heap.blocks[block]->cells + BITS_PER_WORD * wordInBitmap + bitInWord);
     392    CollectorBlock *curBlock = heap.blocks[block];
     393    for (int cell = 0; cell < CELLS_PER_BLOCK; cell++) {
     394      ValueImp *imp = (ValueImp *)(curBlock->cells + cell);
     395     
     396      if (((CollectorCell *)imp)->u.freeCell.zeroIfFree != 0 &&
     397          ((imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount != 0)) {
     398        const char *mangled_name = typeid(*imp).name();
     399        int status;
     400        char *demangled_name = __cxxabiv1::__cxa_demangle (mangled_name, NULL, NULL, &status);
    370401       
    371         if (word & (1 << bitInWord)
    372                 && ((imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount != 0)) {
    373           const char *mangled_name = typeid(*imp).name();
    374           int status;
    375           char *demangled_name = __cxxabiv1::__cxa_demangle (mangled_name, NULL, NULL, &status);
    376          
    377           CFStringRef className = CFStringCreateWithCString(NULL, demangled_name, kCFStringEncodingASCII);
    378           free(demangled_name);
    379           CFSetAddValue(classes, className);
    380           CFRelease(className);
    381         }
     402        CFStringRef className = CFStringCreateWithCString(NULL, demangled_name, kCFStringEncodingASCII);
     403        free(demangled_name);
     404        CFSetAddValue(classes, className);
     405        CFRelease(className);
    382406      }
    383407    }
     
    388412   
    389413    if ((imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount != 0) {
    390         const char *mangled_name = typeid(*imp).name();
    391         int status;
    392         char *demangled_name = __cxxabiv1::__cxa_demangle (mangled_name, NULL, NULL, &status);
    393        
    394         CFStringRef className = CFStringCreateWithCString(NULL, demangled_name, kCFStringEncodingASCII);
    395         free(demangled_name);
    396         CFSetAddValue(classes, className);
    397         CFRelease(className);
    398     }
    399   }
    400 
     414      const char *mangled_name = typeid(*imp).name();
     415      int status;
     416      char *demangled_name = __cxxabiv1::__cxa_demangle (mangled_name, NULL, NULL, &status);
     417     
     418      CFStringRef className = CFStringCreateWithCString(NULL, demangled_name, kCFStringEncodingASCII);
     419      free(demangled_name);
     420      CFSetAddValue(classes, className);
     421      CFRelease(className);
     422    }
     423  }
     424 
    401425  return classes;
    402426}
Note: See TracChangeset for help on using the changeset viewer.