Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/jitruby/ext/jit.c  view on Meta::CPAN

 *   Context.build { |context| ... }
 *
 * Create a context and acquire a lock on it, then yield the context to
 * the block.
 */
static VALUE context_s_build(VALUE klass)
{
  return context_build(context_s_new(klass));
}

/* ---------------------------------------------------------------------------
 * Closure
 * ---------------------------------------------------------------------------
 */

static void mark_closure(struct Closure * closure)
{
  rb_gc_mark(closure->function);
}

VALUE closure_to_int(VALUE self)
{
  struct Closure * closure;
  Data_Get_Struct(self, struct Closure, closure);
  VALUE v = ULONG2NUM((unsigned long)closure->function_ptr);
  return v;
}

VALUE closure_to_s(VALUE self)
{
  struct Closure * closure;
  VALUE args[4];
  Data_Get_Struct(self, struct Closure, closure);
  args[0] = rb_str_new2("#<JIT::Closure:0x%x function=%s function_ptr=0x%x>");
  args[1] = ULONG2NUM((unsigned long)self);
  args[2] = rb_any_to_s(closure->function);
  args[3] = ULONG2NUM((unsigned long)closure->function_ptr);
  return rb_f_sprintf(sizeof(args)/sizeof(args[0]), args);
}

VALUE closure_inspect(VALUE self)
{
  return closure_to_s(self);
}

/* ---------------------------------------------------------------------------
 * Function
 * ---------------------------------------------------------------------------
 */

static void mark_function(jit_function_t function)
{
  rb_gc_mark((VALUE)jit_function_get_meta(function, RJT_VALUE_OBJECTS));
  rb_gc_mark((VALUE)jit_function_get_meta(function, RJT_CONTEXT));
}

static VALUE create_function(int argc, VALUE * argv, VALUE klass)
{
  VALUE context_v;
  VALUE signature_v;
  VALUE parent_function_v;

  jit_function_t function;
  jit_function_t parent_function;
  jit_context_t context;
  jit_type_t signature;
  jit_type_t untagged_signature;

  VALUE function_v;
  VALUE functions;

  int signature_tag;

  rb_scan_args(argc, argv, "21", &context_v, &signature_v, &parent_function_v);

  Data_Get_Struct(context_v, struct _jit_context, context);
  Data_Get_Struct(signature_v, struct _jit_type, signature);

  signature_tag = jit_type_get_kind(signature);

  /* If this signature was tagged, get the untagged type */
  if((untagged_signature = jit_type_get_tagged_type(signature)))
  {
    signature = untagged_signature;
  }

  if(RTEST(parent_function_v))
  {
    /* If this function has a parent, then it is a nested function */
    Data_Get_Struct(parent_function_v, struct _jit_function, parent_function);
    function = jit_function_create_nested(context, signature, parent_function);
  }
  else
  {
    /* Otherwise, it's a standalone function */
    function = jit_function_create(context, signature);
  }

  /* Make sure the function is around as long as the context is */
  if(!jit_function_set_meta(function, RJT_VALUE_OBJECTS, (void *)rb_ary_new(), 0, 0))
  {
    rb_raise(rb_eNoMemError, "Out of memory");
  }

  /* Remember the signature's tag for later */
  if(!jit_function_set_meta(function, RJT_TAG_FOR_SIGNATURE, (void *)signature_tag, 0, 0))
  {
    rb_raise(rb_eNoMemError, "Out of memory");
  }

  /* And remember the function's context for later */
  if(!jit_function_set_meta(function, RJT_CONTEXT, (void *)context_v, 0, 0))
  {
    rb_raise(rb_eNoMemError, "Out of memory");
  }

  function_v = Data_Wrap_Struct(rb_cFunction, mark_function, 0, function);

  /* Add this function to the context's list of functions */
  functions = (VALUE)jit_context_get_meta(context, RJT_FUNCTIONS);
  rb_ary_push(functions, function_v);

  return function_v;
}

/*
 * call-seq:
 *   function.compile()
 *
 * Begin compiling a function.
 */
static VALUE function_compile(VALUE self)
{
  jit_function_t function;
  Data_Get_Struct(self, struct _jit_function, function);
  if(!jit_function_compile(function))
  {
    rb_raise(rb_eRuntimeError, "Unable to compile function");
  }
  return self;
}

/*
 * call-seq:
 *   function = Function.new(context, signature, [parent])
 *
 * Create a new function.
 */
static VALUE function_s_new(int argc, VALUE * argv, VALUE klass)
{
  if(rb_block_given_p())
  {
    rb_raise(rb_eArgError, "Function.new does not take a block");
  }

  return create_function(argc, argv, klass);
}

static VALUE function_abandon_if_exception(VALUE function_v)
{
  if(ruby_errinfo)
  {
    jit_function_t function;
    Data_Get_Struct(function_v, struct _jit_function, function);
    jit_function_abandon(function);
  }
  return Qnil;
}

/*
 * call-seq:
 *   function = Function.new(context, signature, [parent]) { |function| ... }
 *
 * Create a new function, begin compiling it, and pass the function to
 * the block.
 */
static VALUE function_s_compile(int argc, VALUE * argv, VALUE klass)
{
  VALUE function = create_function(argc, argv, klass);
  rb_yield(function);
  function_compile(function);
#ifdef HAVE_RB_ENSURE
  rb_ensure(
      function_compile,
      function,
      function_abandon_if_exception,
      function);
#else
  /* Rubinius does not yet have rb_ensure */
  function_compile(function);
  function_abandon_if_exception(function);
#endif
  return function;
}

/*
 * Get the value that corresponds to a specified function parameter.
 *
 * call-seq:
 *   value = function.get_param(index)
 */
static VALUE function_get_param(VALUE self, VALUE idx)
{
  jit_function_t function;
  jit_value_t value;
  Data_Get_Struct(self, struct _jit_function, function);
  value = jit_value_get_param(function, NUM2INT(idx));
  raise_memory_error_if_zero(value);
  return Data_Wrap_Struct(rb_cValue, 0, 0, value);
}

#include "insns.inc"

static VALUE function_value_klass(VALUE self, VALUE type_v, VALUE klass)
{
  jit_function_t function;
  jit_type_t type;
  jit_value_t value;

  Data_Get_Struct(self, struct _jit_function, function);

  type_v = lookup_const(rb_cType, type_v);
  check_type("type", rb_cType, type_v);
  Data_Get_Struct(type_v, struct _jit_type, type);

  /* TODO: When we wrap a value, we should inject a reference to the
   * function in the object, so the function stays around as long as the
   * value does */
  value = jit_value_create(function, type);
  return Data_Wrap_Struct(klass, 0, 0, value);
}



( run in 1.273 second using v1.01-cache-2.11-cpan-4991d5b9bd9 )