Exemple #1
0
INLINE void
_syx_memory_gc_mark (SyxOop object)
{
  syx_varsize i;

  if (!SYX_IS_OBJECT (object) || SYX_OBJECT_IS_MARKED(object) || SYX_IS_NIL(syx_object_get_class (object)))
    return;

  SYX_OBJECT_IS_MARKED(object) = TRUE;

  _syx_memory_gc_mark (SYX_OBJECT(object)->klass);

  /* Only the used stack part of the process must be marked */
  if (SYX_OOP_EQ (syx_object_get_class (object), syx_process_class))
    {
      SyxOop stack = SYX_PROCESS_STACK (object);
      SyxInterpFrame *frame = SYX_OOP_CAST_POINTER (SYX_PROCESS_FRAME_POINTER (object));
      syx_int32 offset = SYX_POINTERS_OFFSET (frame->stack,
                                              SYX_OBJECT_DATA (stack));

      SYX_OBJECT_IS_MARKED(stack) = TRUE;

      /* First mark variables except the process stack */
      for (i=0; i < SYX_VARS_PROCESS_STACK; i++)
        _syx_memory_gc_mark (SYX_OBJECT_VARS(object)[i]);

      /* Mark detached frames */
      while (frame)
        {
          _syx_memory_gc_mark (frame->detached_frame);
          frame = frame->parent_frame;
        }

      /* Now mark the stack */
      for (i=0; i < offset; i++)
        _syx_memory_gc_mark (SYX_OBJECT_DATA(stack)[i]);

      /* Mark variables after the process stack */
      for (i=SYX_VARS_PROCESS_STACK+1; i < syx_object_vars_size (object); i++)
        _syx_memory_gc_mark (SYX_OBJECT_VARS(object)[i]);

      /* Process has no data */
      return;
    }
  else
    {
      for (i=0; i < syx_object_vars_size (object); i++)
        _syx_memory_gc_mark (SYX_OBJECT_VARS(object)[i]);
    }

  if (SYX_OBJECT_HAS_REFS (object))
    {
      for (i=0; i < SYX_OBJECT_DATA_SIZE (object); i++)
        _syx_memory_gc_mark (SYX_OBJECT_DATA(object)[i]);
    }
}
Exemple #2
0
INLINE void
_syx_memory_gc_mark (SyxOop object)
{
  syx_varsize i;
  if (!SYX_IS_OBJECT (object) || SYX_OBJECT_IS_MARKED(object) || SYX_IS_NIL(syx_object_get_class (object)))
    return;

  SYX_OBJECT_IS_MARKED(object) = TRUE;

  _syx_memory_gc_mark (SYX_OBJECT(object)->klass);

  for (i=0; i < syx_object_vars_size (object); i++)
    _syx_memory_gc_mark (SYX_OBJECT_VARS(object)[i]);

  if (SYX_OBJECT_HAS_REFS (object))
    {
      for (i=0; i < SYX_OBJECT_DATA_SIZE (object); i++)
        _syx_memory_gc_mark (SYX_OBJECT_DATA(object)[i]);
    }
}
Exemple #3
0
/*!
  Dumps all the memory.

  \param path the file path to put all inside
  \return FALSE if an error occurred
*/
syx_bool
syx_memory_save_image (syx_symbol path)
{
  SyxObject *object;
  FILE *image;
  syx_int32 data = 0;
  SyxObject *stack;
  SyxOop process;

  if (!path)
    path = SYX_OBJECT_SYMBOL (syx_globals_at ("ImageFileName"));

  if (!path)
    return FALSE;

  image = fopen (path, "wb");
  if (!image)
    return FALSE;

  syx_memory_gc ();

  data = SYX_COMPAT_SWAP_32 (_syx_memory_size);
  fwrite (&data, sizeof (syx_int32), 1, image);
  data = SYX_COMPAT_SWAP_32 (_syx_freed_memory_top);
  fwrite (&data, sizeof (syx_int32), 1, image);
  _syx_memory_write (_syx_freed_memory, FALSE, _syx_freed_memory_top, image);

  _syx_scheduler_save (image);

  _syx_memory_write (&syx_globals, FALSE, 1, image);
  _syx_memory_write (&syx_symbols, FALSE, 1, image);

  /* First store the processes */
  process = syx_processor_active_process;
  if (!SYX_IS_NIL (process))
    {
      do
        {
          _syx_memory_write_process_stack (SYX_OBJECT (process), image);
          process = SYX_PROCESS_NEXT (process);
        } while (SYX_OOP_NE (process, syx_processor_active_process));
    }

  for (object=syx_memory; object <= SYX_MEMORY_TOP; object++)
    {
      /* the mark check is not related to the GC but means the object has been already written */
      if (SYX_IS_NIL (object->klass) || object->is_marked)
        continue;

      _syx_memory_write_object_with_vars (object, image);

      /* store data */
      data = SYX_COMPAT_SWAP_32 (object->data_size);
      fwrite (&data, sizeof (syx_varsize), 1, image);
      if (object->data_size > 0)
        {
          if (object->has_refs)
            _syx_memory_write (object->data, TRUE, object->data_size, image);
          else
            {
#ifdef HAVE_LIBGMP
              if (SYX_OBJECT_IS_LARGE_INTEGER ((SyxOop)object))
                {
                  /* This algorithm is used to store large integers.
                     We need to specify how many bytes GMP wrote to the image,
                     for systems that don't support GMP */

                  syx_int32 offset = 0;
                  syx_nint start, end;
                  /* specify that's a large integer */
                  fputc (SYX_MEMORY_TYPE_LARGE_INTEGER, image);
                  /* make space to hold the offset */
                  fwrite (&offset, sizeof (syx_int32), 1, image);
                  start = ftell (image);
                  mpz_out_raw (image, SYX_OBJECT_LARGE_INTEGER ((SyxOop)object));
                  end = ftell (image);
                  offset = end - start;
                  /* go back to the offset */
                  fseek (image, - offset - sizeof (syx_int32), SEEK_CUR);
                  /* now write the length of the data written by mpz_out_raw () */
                  data = SYX_COMPAT_SWAP_32 (offset);
                  fwrite (&data, sizeof (syx_int32), 1, image);
                  /* return again to continue normal writing */
                  fseek (image, offset, SEEK_CUR);
                }
              else
#endif /* HAVE_LIBGMP */
                {
                  /* it's not a large integer */
                  fputc (SYX_MEMORY_TYPE_NORMAL, image);
                  fwrite (object->data, sizeof (syx_int8), object->data_size, image);
                }
            }
        }

      /* Check for block closures that are not attached to any process */
      if (SYX_OOP_EQ (object->klass, syx_block_closure_class))
        {
          stack = SYX_OBJECT (object->vars[SYX_VARS_BLOCK_CLOSURE_OUTER_FRAME]);
          /* Check if the stack has been collected or written to the image */
          if (SYX_IS_NIL (SYX_POINTER_CAST_OOP (stack)) || stack->is_marked)
            continue;

          _syx_memory_write_object_with_vars (stack, image);

          data = SYX_COMPAT_SWAP_32 (stack->data_size);
          fwrite (&data, sizeof (syx_varsize), 1, image);
          /* Store the index of this frame */
          fputc (SYX_MEMORY_TYPE_BOF, image);
          data = SYX_COMPAT_SWAP_32 (0);
          fwrite (&data, sizeof (syx_varsize), 1, image);
          /* Outer frames have only one frame */
          _syx_memory_write_frame (NULL, (SyxInterpFrame *)stack->data, NULL, image);
          fputc (SYX_MEMORY_TYPE_EOS, image);
          fwrite (&data, sizeof (syx_varsize), 1, image);
          
          stack->is_marked = TRUE;
        }
    }

  fclose (image);

  /* be sure all objects are unmarked */
  for (object=syx_memory; object <= SYX_MEMORY_TOP; object++)
    object->is_marked = FALSE;

  return TRUE;
}
Exemple #4
0
/* Dump the whole stack of the process.
   This will also dump relative objects containing stack, like block closure outerFrames. */
static void
_syx_memory_write_process_stack (SyxObject *process, FILE *image)
{
  syx_int32 data;
  SyxObject *stack = SYX_OBJECT (process->vars[SYX_VARS_PROCESS_STACK]);
  SyxInterpFrame *bottom_frame = (SyxInterpFrame *)stack->data;
  SyxInterpFrame *frame = SYX_OOP_CAST_POINTER (process->vars[SYX_VARS_PROCESS_FRAME_POINTER]);
  SyxInterpFrame *upper_frame = NULL;
  SyxOop *oop;

  if (SYX_IS_NIL (SYX_POINTER_CAST_OOP (stack)))
    return;

  _syx_memory_write_object_with_vars (stack, image);

  /* store data size */
  data = SYX_COMPAT_SWAP_32 (stack->data_size);
  fwrite (&data, sizeof (syx_varsize), 1, image);
  /* We have to do things in reverse order because the stack is such a reverse single linked list,
     each frame connected by parent frames */
  while (frame)
    {
      /* We store detached frames later */
      if (!SYX_IS_NIL (frame->detached_frame))
        {
          frame = frame->parent_frame;
          continue;
        }

      /* Store the index of this frame */
      fputc (SYX_MEMORY_TYPE_BOF, image);
      data = SYX_COMPAT_SWAP_32 (SYX_POINTERS_OFFSET (frame, bottom_frame));
      fwrite (&data, sizeof (syx_varsize), 1, image);
      _syx_memory_write_frame (process, frame, NULL, image);
      upper_frame = frame;
      frame = frame->parent_frame;
    }
  fputc (SYX_MEMORY_TYPE_EOS, image);
  /* We have to store the rest of objects, for detached frames, up to the upper frame.
     What we need is only the local stacks, but we don't know where they begin, so just skip C pointers */
  if (upper_frame)
    {
      data = SYX_COMPAT_SWAP_32 (SYX_POINTERS_OFFSET (upper_frame, bottom_frame));
      fwrite (&data, sizeof (syx_int32), 1, image);
      for (oop = (SyxOop *)bottom_frame; oop != (SyxOop *)upper_frame; oop++)
        {
          if (SYX_IS_CPOINTER (*oop))
            _syx_memory_write (&syx_nil, TRUE, 1, image);
          else
            _syx_memory_write (oop, TRUE, 1, image);
        }
    }
  else
    {
      data = SYX_COMPAT_SWAP_32 (0);
      fwrite (&data, sizeof (syx_int32), 1, image);
    }
  stack->is_marked = TRUE;

  /* Let's store all detached frames until they have a reference to this process */
  frame = SYX_OOP_CAST_POINTER (process->vars[SYX_VARS_PROCESS_FRAME_POINTER]);
  while (frame)
    {
      stack = SYX_OBJECT (frame->detached_frame);
      /* Also check if the stack has been collected */
      if (SYX_IS_NIL (SYX_POINTER_CAST_OOP (stack)) || stack->is_marked)
        {
          frame = frame->parent_frame;
          continue;
        }

      _syx_memory_write_object_with_vars (stack, image);

      data = SYX_COMPAT_SWAP_32 (stack->data_size);
      fwrite (&data, sizeof (syx_varsize), 1, image);    
      /* Store the index of this frame */
      fputc (SYX_MEMORY_TYPE_BOF, image);
      data = SYX_COMPAT_SWAP_32 (0);
      fwrite (&data, sizeof (syx_varsize), 1, image);
      _syx_memory_write_frame (process, frame, NULL, image);
      fputc (SYX_MEMORY_TYPE_EOS, image);
      fwrite (&data, sizeof (syx_varsize), 1, image);

      stack->is_marked = TRUE;
      frame = frame->parent_frame;
    }
}