예제 #1
0
void Collector::markProtectedObjects()
{
  for (int i = 0; i < ProtectedValues::_tableSize; i++) {
    ValueImp *val = ProtectedValues::_table[i].key;
    if (val && !val->marked()) {
      val->mark();
    }
  }
}
void ArrayInstanceImp::mark()
{
  ObjectImp::mark();
  unsigned l = storageLength;
  for (unsigned i = 0; i < l; ++i) {
    ValueImp *imp = storage[i];
    if (imp && !imp->marked())
      imp->mark();
  }
}
예제 #3
0
void Collector::markStackObjectsConservatively(void *start, void *end)
{
  if (start > end) {
    void *tmp = start;
    start = end;
    end = tmp;
  }

  assert(((char *)end - (char *)start) < 0x1000000);
  assert(IS_POINTER_ALIGNED(start));
  assert(IS_POINTER_ALIGNED(end));
  
  char **p = (char **)start;
  char **e = (char **)end;
  
  while (p != e) {
    char *x = *p++;
    if (IS_POINTER_ALIGNED(x) && x) {
      bool good = false;
      for (int block = 0; block < heap.usedBlocks; block++) {
	size_t offset = x - (char *)heap.blocks[block];
	const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
	if (offset <= lastCellOffset && offset % sizeof(CollectorCell) == 0) {
	  good = true;
	  break;
	}
      }
      
      if (!good) {
	int n = heap.usedOversizeCells;
	for (int i = 0; i != n; i++) {
	  if (x == (char *)heap.oversizeCells[i]) {
	    good = true;
	    break;
	  }
	}
      }
      
      if (good && ((CollectorCell *)x)->u.freeCell.zeroIfFree != 0) {
	ValueImp *imp = (ValueImp *)x;
	if (!imp->marked())
	  imp->mark();
      }
    }
  }
}
static int compareWithCompareFunctionForQSort(const void *a, const void *b)
{
    CompareWithCompareFunctionArguments *args = compareWithCompareFunctionArguments;

    ValueImp *va = *(ValueImp **)a;
    ValueImp *vb = *(ValueImp **)b;
    if (va->dispatchType() == UndefinedType) {
        return vb->dispatchType() == UndefinedType ? 0 : 1;
    }
    if (vb->dispatchType() == UndefinedType) {
        return -1;
    }

    args->arguments.clear();
    args->arguments.append(va);
    args->arguments.append(vb);
    double compareResult = args->compareFunction->call
        (args->exec, args->globalObject, args->arguments).toNumber(args->exec);
    return compareResult < 0 ? -1 : compareResult > 0 ? 1 : 0;
}
예제 #5
0
Value &Value::operator=(const Value &v)
{
    ValueImp *tmpRep = v.imp();

    // Avoid the destruction of the object underneath us by
    // incrementing the reference on it first
    if(tmpRep)
    {
        tmpRep->ref();
        // fprintf(stderr, "Value::operator=(%p)(copying %p) imp=%p ref=%d\n", this, &v, tmpRep, tmpRep->refcount);
    }

    if(rep)
    {
        rep->deref();
        // fprintf(stderr, "Value::operator=(%p)(copying %p) old imp=%p ref=%d\n", this, &v, rep, rep->refcount);
    }
    rep = tmpRep;

    return *this;
}
static int compareByStringForQSort(const void *a, const void *b)
{
    ExecState *exec = execForCompareByStringForQSort;
    ValueImp *va = *(ValueImp **)a;
    ValueImp *vb = *(ValueImp **)b;
    if (va->dispatchType() == UndefinedType) {
        return vb->dispatchType() == UndefinedType ? 0 : 1;
    }
    if (vb->dispatchType() == UndefinedType) {
        return -1;
    }
    return compare(va->dispatchToString(exec), vb->dispatchToString(exec));
}
예제 #7
0
bool Collector::collect()
{
  assert(Interpreter::lockCount() > 0);

  bool deleted = false;

#if TEST_CONSERVATIVE_GC
  // CONSERVATIVE MARK: mark the root set using conservative GC bit (will compare later)
  ValueImp::useConservativeMark(true);
#endif

#if USE_CONSERVATIVE_GC || TEST_CONSERVATIVE_GC
  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);
  }

  markStackObjectsConservatively();
  markProtectedObjects();
#endif

#if TEST_CONSERVATIVE_GC
  ValueImp::useConservativeMark(false);
#endif

#if !USE_CONSERVATIVE_GC
  // 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();
    }
  }
#endif

  // 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 USE_CONSERVATIVE_GC
	if (!imp->_marked)
#else
	if (!imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED))
#endif
	{
	  //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 {
#if USE_CONSERVATIVE_GC
	  imp->_marked = 0;
#elif TEST_CONSERVATIVE_GC
	  imp->_flags &= ~(ValueImp::VI_MARKED | ValueImp::VI_CONSERVATIVE_MARKED);
#else
	  imp->_flags &= ~ValueImp::VI_MARKED;
#endif
	}
      } 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 USE_CONSERVATIVE_GC
    if (!imp->_marked) {
#else
    if (!imp->refcount && 
	imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) {
#endif

      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 {
#if USE_CONSERVATIVE_GC
      imp->_marked = 0;
#elif TEST_CONSERVATIVE_GC
      imp->_flags &= ~(ValueImp::VI_MARKED | ValueImp::VI_CONSERVATIVE_MARKED);
#else
      imp->_flags &= ~ValueImp::VI_MARKED;
#endif
      cell++;
    }
  }
  
  heap.numAllocationsSinceLastCollect = 0;
  
  memoryFull = (heap.numLiveObjects >= KJS_MEM_LIMIT);

  return deleted;
}

int Collector::size() 
{
  return heap.numLiveObjects; 
}

#ifdef KJS_DEBUG_MEM
void Collector::finalCheck()
{
}
#endif

#if APPLE_CHANGES

int Collector::numInterpreters()
{
  int count = 0;
  if (InterpreterImp::s_hook) {
    InterpreterImp *scr = InterpreterImp::s_hook;
    do {
      ++count;
      scr = scr->next;
    } while (scr != InterpreterImp::s_hook);
  }
  return count;
}
예제 #8
0
bool testInsertDelete(int numInsert, int numDelete, int delOffset, int randSeed) {

  srand(randSeed);
  char str[20];
  bool result = true;

  assert(numDelete >= 0 && numDelete < numInsert);
  assert(delOffset >= 0 && delOffset+numDelete <= numInsert);
  PropertyMap map;

  // add some random numbers
  int *nums = (int*)malloc(numInsert*sizeof(int));
  int i;
  for (i = 0; i < numInsert; i++) {
    nums[i] = int(1000.0*rand()/RAND_MAX);

    Value val = Number(nums[i]);
    ValueImp *v = val.imp();
    v->ref();

    sprintf(str,"%05d-%05d",nums[i],i); // ensure uniqueness
    map.put(str,v,0);
    map.checkTree();
  }

  // check to ensure they're all there
  for (i = 0; i < numInsert; i++) {
    sprintf(str,"%05d-%05d",nums[i],i);
    ValueImp *v = map.get(str);
    if (v == 0 || v->type() != NumberType ||
        static_cast<NumberImp*>(v)->value() != nums[i]) {
      result = false;
    }
    map.checkTree();
  }

  // delete some
  for (i = delOffset; i < delOffset+numDelete; i++) {
    sprintf(str,"%05d-%05d",nums[i],i);
    map.remove(str);
    map.checkTree();
  }

  // make sure the deletes ones aren't there any more, and the others are
  for (i = 0; i < numInsert; i++) {
    sprintf(str,"%05d-%05d",nums[i],i);
    ValueImp *v = map.get(str);

    if (i >= delOffset && i < delOffset+numDelete) {
      // should have been deleted
      if (v)
        result = false;
    }
    else {
      // should not have been deleted
      if (v == 0 || v->type() != NumberType ||
          static_cast<NumberImp*>(v)->value() != nums[i]) {
        result = false;
      }
    }
    map.checkTree();
  }

  // check that first() and next() work
  PropertyMapNode *it = map.first();
  int itcount = 0;
  while (it) {
    itcount++;
    PropertyMapNode *prev = it;
    it = it->next();
    if (it) {
      if (uscompare(prev->name,it->name) >= 0)
        result = false;
    }
  }
  if (itcount != numInsert-numDelete)
    result = false;

  if (result)
    printf("PASS: Insert %d, delete %d-%d, seed %d\n",numInsert,delOffset,
           delOffset+numDelete-1,randSeed);
  else
    printf("FAIL: Insert %d, delete %d-%d, seed %d\n",numInsert,delOffset,
           delOffset+numDelete-1,randSeed);

  return result;
}