Пример #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]);
    }
}
Пример #2
0
/*!
  Enters a new MethodContext or BlockContext.

  \return FALSE if the context was syx_nil
*/
syx_bool
syx_interp_enter_context (SyxOop process, SyxOop context)
{
  SyxOop arguments;
  syx_bool reset_parent_frame = FALSE;
  SyxInterpState _state = SYX_INTERP_STATE_NEW;
  SyxInterpState *state;
  SyxInterpFrame *frame;

  if (SYX_IS_NIL (process) || SYX_IS_NIL (context))
    return FALSE;

  if (SYX_OOP_EQ (process, _syx_interp_state.process))
    state = &_syx_interp_state;
  else 
    {
      state = &_state;
      frame = SYX_OOP_CAST_POINTER (SYX_PROCESS_FRAME_POINTER (process));
      /* This is a new Process, reset the parent_frame once we created the frame */
      if (SYX_IS_NIL (frame->method))
        reset_parent_frame = TRUE;
      state->frame = frame;
      state->process = process;
    }

  arguments = SYX_CONTEXT_PART_ARGUMENTS (context);
  if (SYX_IS_NIL (arguments))
    state->message_arguments_count = 0;
  else
    {
      state->message_arguments_count = SYX_OBJECT_DATA_SIZE (arguments);
      memcpy (state->message_arguments, SYX_OBJECT_DATA (arguments), state->message_arguments_count * sizeof (SyxOop));
    }

  if (SYX_OOP_EQ (syx_object_get_class (context), syx_block_context_class))
    _syx_interp_frame_prepare_new_closure (state, SYX_BLOCK_CONTEXT_CLOSURE (context));
  else
    {
      state->message_receiver = SYX_METHOD_CONTEXT_RECEIVER (context);
      _syx_interp_frame_prepare_new (state, SYX_CONTEXT_PART_METHOD (context));
    }

  if (reset_parent_frame)
    state->frame->stack_return_frame = state->frame->parent_frame = NULL;

  state->frame->this_context = context;
  SYX_CONTEXT_PART_FRAME_POINTER (context) = SYX_POINTER_CAST_OOP (state->frame);
  _syx_interp_save_process_state (state);

  return TRUE;
}
Пример #3
0
/* Fetches and updates the execution state of the interpreter to be ready for next instructions */
static void
_syx_interp_state_update (SyxInterpState *state, SyxInterpFrame *frame)
{
  SyxOop bytecodes;
  SyxOop method = frame->method;;

  state->frame = frame;

  bytecodes = SYX_CODE_BYTECODES (method);
  state->arguments = &frame->local;
  state->temporaries = state->arguments + SYX_SMALL_INTEGER (SYX_CODE_ARGUMENTS_COUNT (method));
  state->method_literals = SYX_OBJECT_DATA (SYX_CODE_LITERALS (method));
  state->method_bytecodes = (syx_uint16 *)SYX_OBJECT_DATA (bytecodes);
  state->method_bytecodes_count = SYX_OBJECT_DATA_SIZE (bytecodes);
}
Пример #4
0
/* Dump a single frame */
static void
_syx_memory_write_frame (SyxObject *process, SyxInterpFrame *frame, SyxInterpFrame *upper_frame, FILE *image)
{
  syx_int32 data;
  SyxInterpFrame *bottom_frame;

  if (!process)
    bottom_frame = NULL;
  else
    bottom_frame = (SyxInterpFrame *)SYX_OBJECT_DATA (process->vars[SYX_VARS_PROCESS_STACK]);

  _syx_memory_write (&frame->this_context, FALSE, 1, image);
  _syx_memory_write (&frame->detached_frame, FALSE, 1, image);
  _syx_memory_write_lazy_pointer (process, frame->parent_frame, image);
  _syx_memory_write_lazy_pointer (process, frame->outer_frame, image);
  _syx_memory_write_lazy_pointer (process, frame->stack_return_frame, image);
  _syx_memory_write (&frame->method, FALSE, 1, image);
  _syx_memory_write (&frame->closure, FALSE, 1, image);
  /* this is not a SmallInteger */
  data = SYX_COMPAT_SWAP_32 (frame->next_instruction);
  fwrite (&data, sizeof (syx_int32), 1, image);
  /* the stack pointer should point inside the process stack itself */
  if (process)
    _syx_memory_write (&process->vars[SYX_VARS_PROCESS_STACK], FALSE, 1, image);
  else
    {
      data = SYX_COMPAT_SWAP_32 (0);
      fwrite (&data, sizeof (syx_int32), 1, image);
    }
  data = SYX_COMPAT_SWAP_32 (SYX_POINTERS_OFFSET (frame->stack, bottom_frame));
  fwrite (&data, sizeof (syx_int32), 1, image);
  _syx_memory_write (&frame->receiver, TRUE, 1, image);
  /* Store arguments, temporaries and local stack.
     Only copy arguments and temporaries for detached frames without following the stack pointer */
  if (SYX_IS_NIL (frame->detached_frame))
    {
      /* if no upper_frame is given, this frame is the top most frame of the process stack */
      if (!upper_frame)
        data = SYX_POINTERS_OFFSET (frame->stack, &frame->local);
      else
        data = SYX_POINTERS_OFFSET (upper_frame, &frame->local);
    }
  else
    data = SYX_OBJECT_DATA_SIZE (frame->detached_frame) - SYX_POINTERS_OFFSET (&frame->local, frame);
  data = SYX_COMPAT_SWAP_32 (data);
  fwrite (&data, sizeof (syx_int32), 1, image);
  _syx_memory_write (&frame->local, TRUE, SYX_COMPAT_SWAP_32 (data), image);
}
Пример #5
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]);
    }
}
Пример #6
0
static syx_bool
_syx_cold_parse_class (SyxLexer *lexer)
{
  SyxToken token = syx_lexer_get_last_token (lexer);
  SyxOop superclass, subclass;
  syx_string subclass_name;
  syx_bool existing_class = TRUE;

  SyxOop inst_vars, class_vars;
  SyxLexer *inst_vars_lexer, *class_vars_lexer;
  syx_varsize super_inst_vars_size;
  syx_int32 i;

  if (token.type != SYX_TOKEN_NAME_CONST)
    {
      syx_error ("Expected a name constant\n");
      syx_token_free (token);
      return FALSE;
    }

  if (!strcmp (token.value.string, "nil"))
    superclass = syx_nil;
  else
    superclass = syx_globals_at (token.value.string);
  
  token = syx_lexer_next_token (lexer);
  if (!(token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "subclass:")))
    {
      syx_token_free (token);
      syx_error ("Expected #subclass:\n");
      return FALSE;
    }
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_SYM_CONST)
    {
      syx_token_free (token);
      syx_error ("Expected a symbol constant\n");
      return FALSE;
    }

  subclass_name = syx_strdup (token.value.string);
  syx_token_free (token);
  subclass = syx_globals_at_if_absent (subclass_name, syx_nil);

  if (strcmp (subclass_name, "Object"))
    {
      if (SYX_IS_NIL (subclass))
        existing_class = FALSE;
      else
        {
          existing_class = TRUE;
          if (SYX_OOP_NE (SYX_CLASS_SUPERCLASS(subclass), superclass))
            {
              syx_array_remove (SYX_CLASS_SUBCLASSES (SYX_CLASS_SUPERCLASS (subclass)),
                                subclass);
              SYX_CLASS_SUPERCLASS(subclass) = superclass;
              syx_array_add (SYX_CLASS_SUBCLASSES (superclass), subclass, TRUE);

              syx_array_remove (SYX_CLASS_SUBCLASSES (SYX_CLASS_SUPERCLASS(syx_object_get_class (subclass))),
                                syx_object_get_class (subclass));
              SYX_CLASS_SUPERCLASS(syx_object_get_class (subclass)) = syx_object_get_class (superclass);
              syx_array_add (SYX_CLASS_SUBCLASSES (syx_object_get_class (superclass)),
                             syx_object_get_class (subclass), TRUE);
            }
        }
    }

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_NAME_COLON)
    {
      syx_token_free (token);
      syx_error ("Expected #instanceVariableNames:\n");
      return FALSE;
    }
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_STR_CONST)
    {
      syx_token_free (token);
      syx_error ("Expected a string as argument for #instanceVariableNames:\n");
      return FALSE;
    }
  inst_vars_lexer = syx_lexer_new (token.value.string);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_NAME_COLON)
    {
      syx_token_free (token);
      syx_error ("Expected #classVariableNames:\n");
      return FALSE;
    }
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_STR_CONST)
    {
      syx_token_free (token);
      syx_error ("Expected a string as argument for #classVariableNames:\n");
      return FALSE;
    }
  class_vars_lexer = syx_lexer_new (token.value.string);

  token = syx_lexer_next_token (lexer);
  if (!_IS_EXL_MARK (token))
    {
      syx_token_free (token);
      syx_error ("Class definition must terminate with an exlamation mark\n");
      return FALSE;
    }
  syx_token_free (token);

  if (!existing_class)
    {
      subclass = syx_class_new (superclass);
      SYX_CLASS_NAME(subclass) = syx_symbol_new (subclass_name);
      syx_globals_at_put (SYX_CLASS_NAME(subclass), subclass);
    }
  syx_free (subclass_name);

  /* Parse instance variables */
  inst_vars = _syx_cold_parse_vars (inst_vars_lexer, FALSE);
  syx_lexer_free (inst_vars_lexer, TRUE);

  /* Fetch superclass instanceSize */
  if (SYX_IS_NIL (superclass))
    super_inst_vars_size = 0;
  else
    super_inst_vars_size = SYX_SMALL_INTEGER (SYX_CLASS_INSTANCE_SIZE (superclass));

  SYX_CLASS_INSTANCE_VARIABLES(subclass) = inst_vars;
  SYX_CLASS_INSTANCE_SIZE(subclass) = syx_small_integer_new (super_inst_vars_size
                                                             + SYX_OBJECT_DATA_SIZE (inst_vars));

  /* Now parse class variables */
  class_vars = _syx_cold_parse_vars (class_vars_lexer, TRUE);
  syx_lexer_free (class_vars_lexer, TRUE);

  SYX_CLASS_CLASS_VARIABLES(subclass) = syx_dictionary_new (SYX_OBJECT_DATA_SIZE (class_vars) + 10); 

  /* translate from array to dictionary */
  for (i=0; i < SYX_OBJECT_DATA_SIZE(class_vars); i++)
    syx_dictionary_at_symbol_put (SYX_CLASS_CLASS_VARIABLES(subclass),
                                  SYX_OBJECT_DATA(class_vars)[i], syx_nil);
  /* get rid of this */
  syx_object_free (class_vars);

  return TRUE;
}