Logo Search packages:      
Sourcecode: osb-jscore version File versions  Download package

bool KJS::Collector::collect (  )  [static]

Run the garbage collection. This involves calling the delete operator on each object and freeing the used memory.

Definition at line 165 of file collector.cpp.

References KJS::ValueImp::_flags, KJS::ValueImp::mark(), KJS::ValueImp::refcount, and KJS::ValueImp::~ValueImp().

Referenced by allocate().

{
  assert(Interpreter::lockCount() > 0);

  bool deleted = false;

  // MARK: first mark all referenced objects recursively
  // starting out from the set of root objects
  if (InterpreterImp::s_hook) {
    InterpreterImp *scr = InterpreterImp::s_hook;
    do {
      //fprintf( stderr, "Collector marking interpreter %p\n",(void*)scr);
      scr->mark();
      scr = scr->next;
    } while (scr != InterpreterImp::s_hook);
  }
  
  // mark any other objects that we wouldn't delete anyway
  for (int block = 0; block < heap.usedBlocks; block++) {

    int minimumCellsToProcess = heap.blocks[block]->usedCells;
    CollectorBlock *curBlock = heap.blocks[block];

    for (int cell = 0; cell < CELLS_PER_BLOCK; cell++) {
      if (minimumCellsToProcess < cell) {
      goto skip_block_mark;
      }
      
      ValueImp *imp = (ValueImp *)(curBlock->cells + cell);

      if (((CollectorCell *)imp)->u.freeCell.zeroIfFree != 0) {
      
      if ((imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
          ((imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount != 0)) {
        imp->mark();
      }
      } else {
      minimumCellsToProcess++;
      }
    }
  skip_block_mark: ;
  }
  
  for (int cell = 0; cell < heap.usedOversizeCells; cell++) {
    ValueImp *imp = (ValueImp *)heap.oversizeCells[cell];
    if ((imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
      ((imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount != 0)) {
      imp->mark();
    }
  }

  // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else
  
  int emptyBlocks = 0;

  for (int block = 0; block < heap.usedBlocks; block++) {
    CollectorBlock *curBlock = heap.blocks[block];

    int minimumCellsToProcess = curBlock->usedCells;

    for (int cell = 0; cell < CELLS_PER_BLOCK; cell++) {
      if (minimumCellsToProcess < cell) {
      goto skip_block_sweep;
      }

      ValueImp *imp = (ValueImp *)(curBlock->cells + cell);

      if (((CollectorCell *)imp)->u.freeCell.zeroIfFree != 0) {
      if (!imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) {
        //fprintf( stderr, "Collector::deleting ValueImp %p (%s)\n", (void*)imp, typeid(*imp).name());
        // emulate destructing part of 'operator delete()'
        imp->~ValueImp();
        curBlock->usedCells--;
        heap.numLiveObjects--;
        deleted = true;

        // put it on the free list
        ((CollectorCell *)imp)->u.freeCell.zeroIfFree = 0;
        ((CollectorCell *)imp)->u.freeCell.next = curBlock->freeList;
        curBlock->freeList = (CollectorCell *)imp;

      } else {
        imp->_flags &= ~ValueImp::VI_MARKED;
      }
      } else {
      minimumCellsToProcess++;
      }
    }

  skip_block_sweep:

    if (heap.blocks[block]->usedCells == 0) {
      emptyBlocks++;
      if (emptyBlocks > SPARE_EMPTY_BLOCKS) {
#if !DEBUG_COLLECTOR
      free(heap.blocks[block]);
#endif
      // swap with the last block so we compact as we go
      heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
      heap.usedBlocks--;
      block--; // Don't move forward a step in this case

      if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
        heap.numBlocks = heap.numBlocks / GROWTH_FACTOR; 
        heap.blocks = (CollectorBlock **)realloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock *));
      }
      } 
    }
  }

  if (deleted) {
    heap.firstBlockWithPossibleSpace = 0;
  }
  
  int cell = 0;
  while (cell < heap.usedOversizeCells) {
    ValueImp *imp = (ValueImp *)heap.oversizeCells[cell];
    
    if (!imp->refcount && 
      imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) {
      
      imp->~ValueImp();
#if DEBUG_COLLECTOR
      heap.oversizeCells[cell]->u.freeCell.zeroIfFree = 0;
#else
      free((void *)imp);
#endif

      // swap with the last oversize cell so we compact as we go
      heap.oversizeCells[cell] = heap.oversizeCells[heap.usedOversizeCells - 1];

      heap.usedOversizeCells--;
      deleted = true;
      heap.numLiveObjects--;

      if (heap.numOversizeCells > MIN_ARRAY_SIZE && heap.usedOversizeCells < heap.numOversizeCells / LOW_WATER_FACTOR) {
      heap.numOversizeCells = heap.numOversizeCells / GROWTH_FACTOR; 
      heap.oversizeCells = (CollectorCell **)realloc(heap.oversizeCells, heap.numOversizeCells * sizeof(CollectorCell *));
      }

    } else {
      imp->_flags &= ~ValueImp::VI_MARKED;
      cell++;
    }
  }
  
  heap.numAllocationsSinceLastCollect = 0;
  
  memoryFull = (heap.numLiveObjects >= KJS_MEM_LIMIT);

  return deleted;
}


Generated by  Doxygen 1.6.0   Back to index