コード例 #1
0
ファイル: wren_value.c プロジェクト: Zhangli88/wren
static void markFiber(WrenVM* vm, ObjFiber* fiber)
{
  if (setMarkedFlag(&fiber->obj)) return;

  // Stack functions.
  for (int i = 0; i < fiber->numFrames; i++)
  {
    wrenMarkObj(vm, fiber->frames[i].fn);
  }

  // Stack variables.
  for (Value* slot = fiber->stack; slot < fiber->stackTop; slot++)
  {
    wrenMarkValue(vm, *slot);
  }

  // Open upvalues.
  Upvalue* upvalue = fiber->openUpvalues;
  while (upvalue != NULL)
  {
    markUpvalue(vm, upvalue);
    upvalue = upvalue->next;
  }

  // The caller.
  if (fiber->caller != NULL) markFiber(vm, fiber->caller);

  if (fiber->error != NULL) markString(vm, fiber->error);

  // Keep track of how much memory is still in use.
  vm->bytesAllocated += sizeof(ObjFiber);
  // TODO: Count size of error message buffer.
}
コード例 #2
0
ファイル: wren_value.c プロジェクト: Zhangli88/wren
static void markUpvalue(WrenVM* vm, Upvalue* upvalue)
{
  // This can happen if a GC is triggered in the middle of initializing the
  // closure.
  if (upvalue == NULL) return;

  if (setMarkedFlag(&upvalue->obj)) return;

  // Mark the closed-over object (in case it is closed).
  wrenMarkValue(vm, upvalue->closed);

  // Keep track of how much memory is still in use.
  vm->bytesAllocated += sizeof(Upvalue);
}
コード例 #3
0
ファイル: wren_value.c プロジェクト: Zhangli88/wren
static void markInstance(WrenVM* vm, ObjInstance* instance)
{
  if (setMarkedFlag(&instance->obj)) return;

  markClass(vm, instance->obj.classObj);

  // Mark the fields.
  for (int i = 0; i < instance->obj.classObj->numFields; i++)
  {
    wrenMarkValue(vm, instance->fields[i]);
  }

  // Keep track of how much memory is still in use.
  vm->bytesAllocated += sizeof(ObjInstance);
  vm->bytesAllocated += sizeof(Value) * instance->obj.classObj->numFields;
}
コード例 #4
0
ファイル: wren_value.c プロジェクト: Zhangli88/wren
static void markList(WrenVM* vm, ObjList* list)
{
  if (setMarkedFlag(&list->obj)) return;

  // Mark the elements.
  Value* elements = list->elements;
  for (int i = 0; i < list->count; i++)
  {
    wrenMarkValue(vm, elements[i]);
  }

  // Keep track of how much memory is still in use.
  vm->bytesAllocated += sizeof(ObjList);
  if (list->elements != NULL)
  {
    vm->bytesAllocated += sizeof(Value) * list->capacity;
  }
}
コード例 #5
0
ファイル: wren_value.c プロジェクト: Zhangli88/wren
static void markFn(WrenVM* vm, ObjFn* fn)
{
  if (setMarkedFlag(&fn->obj)) return;

  // Mark the constants.
  for (int i = 0; i < fn->numConstants; i++)
  {
    wrenMarkValue(vm, fn->constants[i]);
  }

  wrenMarkObj(vm, (Obj*)fn->debug->sourcePath);

  // Keep track of how much memory is still in use.
  vm->bytesAllocated += sizeof(ObjFn);
  vm->bytesAllocated += sizeof(uint8_t) * fn->bytecodeLength;
  vm->bytesAllocated += sizeof(Value) * fn->numConstants;

  // The debug line number buffer.
  vm->bytesAllocated += sizeof(int) * fn->bytecodeLength;

  // TODO: What about the function name?
}
コード例 #6
0
ファイル: wren_vm.c プロジェクト: zeckalpha/wren
static void collectGarbage(WrenVM* vm)
{
#if WREN_DEBUG_TRACE_MEMORY || WREN_DEBUG_TRACE_GC
  printf("-- gc --\n");

  size_t before = vm->bytesAllocated;
  double startTime = (double)clock() / CLOCKS_PER_SEC;
#endif

  // Mark all reachable objects.

  // Reset this. As we mark objects, their size will be counted again so that
  // we can track how much memory is in use without needing to know the size
  // of each *freed* object.
  //
  // This is important because when freeing an unmarked object, we don't always
  // know how much memory it is using. For example, when freeing an instance,
  // we need to know its class to know how big it is, but it's class may have
  // already been freed.
  vm->bytesAllocated = 0;

  // Global variables.
  for (int i = 0; i < vm->globals.count; i++)
  {
    wrenMarkValue(vm, vm->globals.data[i]);
  }

  // Pinned objects.
  WrenPinnedObj* pinned = vm->pinned;
  while (pinned != NULL)
  {
    wrenMarkObj(vm, pinned->obj);
    pinned = pinned->previous;
  }

  // The current fiber.
  if (vm->fiber != NULL) wrenMarkObj(vm, (Obj*)vm->fiber);

  // Any object the compiler is using (if there is one).
  if (vm->compiler != NULL) wrenMarkCompiler(vm, vm->compiler);

  // Collect any unmarked objects.
  Obj** obj = &vm->first;
  while (*obj != NULL)
  {
    if (!((*obj)->flags & FLAG_MARKED))
    {
      // This object wasn't reached, so remove it from the list and free it.
      Obj* unreached = *obj;
      *obj = unreached->next;
      wrenFreeObj(vm, unreached);
    }
    else
    {
      // This object was reached, so unmark it (for the next GC) and move on to
      // the next.
      (*obj)->flags &= ~FLAG_MARKED;
      obj = &(*obj)->next;
    }
  }

  vm->nextGC = vm->bytesAllocated * vm->heapScalePercent / 100;
  if (vm->nextGC < vm->minNextGC) vm->nextGC = vm->minNextGC;

#if WREN_DEBUG_TRACE_MEMORY || WREN_DEBUG_TRACE_GC
  double elapsed = ((double)clock() / CLOCKS_PER_SEC) - startTime;
  printf("GC %ld before, %ld after (%ld collected), next at %ld. Took %.3fs.\n",
         before, vm->bytesAllocated, before - vm->bytesAllocated, vm->nextGC,
         elapsed);
#endif
}