コード例 #1
0
ファイル: heap.c プロジェクト: jonas-l/ponyc
size_t heap_size(chunk_t* chunk)
{
  if(chunk->size >= HEAP_SIZECLASSES)
    return chunk->size;

  return SIZECLASS_SIZE(chunk->size);
}
コード例 #2
0
ファイル: heap.c プロジェクト: jonas-l/ponyc
static size_t sweep_small(chunk_t* chunk, chunk_t** avail, chunk_t** full,
  uint32_t empty)
{
  size_t used = 0;
  chunk_t* next;

  while(chunk != NULL)
  {
    next = chunk->next;
    chunk->slots &= chunk->shallow;

    if(chunk->slots == 0)
    {
      used += sizeof(block_t);
      chunk->next = *full;
      *full = chunk;
    } else if(chunk->slots == empty) {
      destroy_small(chunk);
    } else {
      used += sizeof(block_t) -
        (__pony_popcount(chunk->slots) * SIZECLASS_SIZE(chunk->size));
      chunk->next = *avail;
      *avail = chunk;
    }

    chunk = next;
  }

  return used;
}
コード例 #3
0
ファイル: heap.c プロジェクト: JamesLinus/ponyc
void ponyint_heap_endgc(heap_t* heap)
{
  size_t used = 0;

  for(int i = 0; i < HEAP_SIZECLASSES; i++)
  {
    chunk_t* list1 = heap->small_free[i];
    chunk_t* list2 = heap->small_full[i];

    heap->small_free[i] = NULL;
    heap->small_full[i] = NULL;

    chunk_t** avail = &heap->small_free[i];
    chunk_t** full = &heap->small_full[i];

    size_t size = SIZECLASS_SIZE(i);
    uint32_t empty = sizeclass_empty[i];

    used += sweep_small(list1, avail, full, empty, size);
    used += sweep_small(list2, avail, full, empty, size);
  }

  heap->large = sweep_large(heap->large, &used);

  // Foreign object sizes will have been added to heap->used already. Here we
  // add local object sizes as well and set the next gc point for when memory
  // usage has increased.
  heap->used += used;
  heap->next_gc = (size_t)((double)heap->used * heap_nextgc_factor);

  if(heap->next_gc < heap_initialgc)
    heap->next_gc = heap_initialgc;
}
コード例 #4
0
void* ponyint_heap_realloc(pony_actor_t* actor, heap_t* heap, void* p,
  size_t size)
{
  if(p == NULL)
    return ponyint_heap_alloc(actor, heap, size);

  chunk_t* chunk = (chunk_t*)ponyint_pagemap_get(p);

  if(chunk == NULL)
  {
    // Get new memory and copy from the old memory.
    void* q = ponyint_heap_alloc(actor, heap, size);
    memcpy(q, p, size);
    return q;
  }

  size_t oldsize;

  if(chunk->size < HEAP_SIZECLASSES)
  {
    // Previous allocation was a ponyint_heap_alloc_small.
    void* ext = EXTERNAL_PTR(p, chunk->size);

    // If the new allocation is a ponyint_heap_alloc_small and the pointer is
    // not an internal pointer, we may be able to reuse this memory. If it is
    // an internal pointer, we know where the old allocation begins but not
    // where it ends, so we cannot reuse this memory.
    if((size <= HEAP_MAX) && (p == ext))
    {
      uint32_t sizeclass = ponyint_heap_index(size);

      // If the new allocation is the same size or smaller, return the old
      // one.
      if(sizeclass <= chunk->size)
        return p;
    }

    oldsize = SIZECLASS_SIZE(chunk->size) - ((uintptr_t)p - (uintptr_t)ext);
  } else {
    // Previous allocation was a ponyint_heap_alloc_large.
    if((size <= chunk->size) && (p == chunk->m))
    {
      // If the new allocation is the same size or smaller, and this is not an
      // internal pointer, return the old one. We can't reuse internal
      // pointers in large allocs for the same reason as small ones.
      return p;
    }

    oldsize = chunk->size - ((uintptr_t)p - (uintptr_t)chunk->m);
  }

  // Determine how much memory to copy.
  if(oldsize > size)
    oldsize = size;

  // Get new memory and copy from the old memory.
  void* q = ponyint_heap_alloc(actor, heap, size);
  memcpy(q, p, oldsize);
  return q;
}
コード例 #5
0
ファイル: heap.c プロジェクト: jonas-l/ponyc
void* heap_alloc_small(pony_actor_t* actor, heap_t* heap,
  uint32_t sizeclass)
{
  chunk_t* chunk = heap->small_free[sizeclass];
  void* m;

  // If there are none in this size class, get a new one.
  if(chunk != NULL)
  {
    // Clear and use the first available slot.
    uint32_t slots = chunk->slots;
    uint32_t bit = __pony_ffs(slots) - 1;
    slots &= ~(1 << bit);

    m = chunk->m + (bit << HEAP_MINBITS);
    chunk->slots = slots;

    if(slots == 0)
    {
      heap->small_free[sizeclass] = chunk->next;
      chunk->next = heap->small_full[sizeclass];
      heap->small_full[sizeclass] = chunk;
    }
  } else {
    chunk_t* n = (chunk_t*) POOL_ALLOC(chunk_t);
    n->actor = actor;
    n->m = (char*) POOL_ALLOC(block_t);
    n->size = sizeclass;

    // Clear the first bit.
    n->shallow = n->slots = sizeclass_init[sizeclass];
    n->next = NULL;

    pagemap_set(n->m, n);

    heap->small_free[sizeclass] = n;
    chunk = n;

    // Use the first slot.
    m = chunk->m;
  }

  heap->used += SIZECLASS_SIZE(sizeclass);
  return m;
}
コード例 #6
0
ファイル: heap.c プロジェクト: JamesLinus/ponyc
void* ponyint_heap_realloc(pony_actor_t* actor, heap_t* heap, void* p,
  size_t size)
{
  if(p == NULL)
    return ponyint_heap_alloc(actor, heap, size);

  chunk_t* chunk = (chunk_t*)ponyint_pagemap_get(p);

  if(chunk == NULL)
  {
    // Get new memory and copy from the old memory.
    void* q = ponyint_heap_alloc(actor, heap, size);
    memcpy(q, p, size);
    return q;
  }

  if(chunk->size < HEAP_SIZECLASSES)
  {
    // Previous allocation was a ponyint_heap_alloc_small.
    if(size <= HEAP_MAX)
    {
      uint32_t sizeclass = ponyint_heap_index(size);

      // If the new allocation is the same size or smaller, return the old one.
      if(sizeclass <= chunk->size)
        return p;
    }

    // Get new memory and copy from the old memory.
    void* q = ponyint_heap_alloc(actor, heap, size);
    memcpy(q, p, SIZECLASS_SIZE(chunk->size));
    return q;
  }

  // Previous allocation was a ponyint_heap_alloc_large.
  if(size <= chunk->size)
    return p;

  // Get new memory and copy from the old memory.
  void* q = ponyint_heap_alloc(actor, heap, size);
  memcpy(q, p, chunk->size);
  return q;
}