Exemplo n.º 1
0
void
mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
    struct RClass *c = mrb->ci->proc->target_class;

    if (!c) c = mrb->ci->target_class;
    while (c) {
        if (c->iv) {
            iv_tbl *t = c->iv;

            if (iv_get(mrb, t, sym, NULL)) {
                mrb_write_barrier(mrb, (struct RBasic*)c);
                iv_put(mrb, t, sym, v);
                return;
            }
        }
        c = c->super;
    }
    c = mrb->ci->target_class;
    if (!c->iv) {
        c->iv = iv_new(mrb);
    }
    mrb_write_barrier(mrb, (struct RBasic*)c);
    iv_put(mrb, c->iv, sym, v);
}
Exemplo n.º 2
0
void
mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v)
{
    struct RClass * cls = c;

    while (c) {
        if (c->iv) {
            iv_tbl *t = c->iv;

            if (iv_get(mrb, t, sym, NULL)) {
                mrb_write_barrier(mrb, (struct RBasic*)c);
                iv_put(mrb, t, sym, v);
                return;
            }
        }
        c = c->super;
    }

    if (!cls->iv) {
        cls->iv = iv_new(mrb);
    }

    mrb_write_barrier(mrb, (struct RBasic*)cls);
    iv_put(mrb, cls->iv, sym, v);
}
Exemplo n.º 3
0
Arquivo: gc.c Projeto: anehing/mruby
void
test_mrb_write_barrier(void)
{
  mrb_state *mrb = mrb_open();
  struct RBasic *obj;

  puts("test_mrb_write_barrier");
  obj = mrb_basic_ptr(mrb_ary_new(mrb));
  paint_black(obj);

  puts("  in GC_STATE_MARK");
  mrb->gc_state = GC_STATE_MARK;
  mrb_write_barrier(mrb, obj);

  mrb_assert(is_gray(obj));
  mrb_assert(mrb->atomic_gray_list == obj);


  puts("  fail with gray");
  paint_gray(obj);
  mrb_write_barrier(mrb, obj);

  mrb_assert(is_gray(obj));

  mrb_close(mrb);
}
Exemplo n.º 4
0
/*
 *  call-seq:
 *     fiber.resume(args, ...) -> obj
 *
 *  Resumes the fiber from the point at which the last <code>Fiber.yield</code>
 *  was called, or starts running it if it is the first call to
 *  <code>resume</code>. Arguments passed to resume will be the value of
 *  the <code>Fiber.yield</code> expression or will be passed as block
 *  parameters to the fiber's block if this is the first <code>resume</code>.
 *
 *  Alternatively, when resume is called it evaluates to the arguments passed
 *  to the next <code>Fiber.yield</code> statement inside the fiber's block
 *  or to the block value if it runs to completion without any
 *  <code>Fiber.yield</code>
 */
static mrb_value
fiber_resume(mrb_state *mrb, mrb_value self)
{
  struct mrb_context *c = fiber_check(mrb, self);
  mrb_value *a;
  int len;
  mrb_callinfo *ci;

  for (ci = c->ci; ci >= c->cibase; ci--) {
    if (ci->acc < 0) {
      mrb_raise(mrb, E_ARGUMENT_ERROR, "can't cross C function boundary");
    }
  }
  if (c->status == MRB_FIBER_RESUMED) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "double resume");
  }
  if (c->status == MRB_FIBER_TERMINATED) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "resuming dead fiber");
  }
  mrb_get_args(mrb, "*", &a, &len);
  mrb->c->status = MRB_FIBER_RESUMED;
  if (c->status == MRB_FIBER_CREATED) {
    mrb_value *b = c->stack+1;
    mrb_value *e = b + len;

    while (b<e) {
      *b++ = *a++;
    }
    c->cibase->argc = len;
    c->prev = mrb->c;
    if (c->prev->fib) 
      mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib);
    mrb_write_barrier(mrb, (struct RBasic*)c->fib);
    c->status = MRB_FIBER_RUNNING;
    mrb->c = c;

    MARK_CONTEXT_MODIFY(c);
    return c->ci->proc->env->stack[0];
  }
  MARK_CONTEXT_MODIFY(c);
  c->prev = mrb->c;
  if (c->prev->fib) 
    mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib);
  mrb_write_barrier(mrb, (struct RBasic*)c->fib);
  c->status = MRB_FIBER_RUNNING;
  mrb->c = c;
  return fiber_result(mrb, a, len);
}
Exemplo n.º 5
0
Arquivo: fiber.c Projeto: ASnow/mruby
/*
 *  call-seq:
 *     fiber.transfer(args, ...) -> obj
 *
 *  Transfers control to receiver fiber of the method call.
 *  Unlike <code>resume</code> the receiver wouldn't be pushed to call
 * stack of fibers. Instead it will switch to the call stack of
 * transferring fiber.
 *  When resuming a fiber that was transferred to another fiber it would
 * cause double resume error. Though when the fiber is re-transferred
 * and <code>Fiber.yield</code> is called, the fiber would be resumable.
 */
static mrb_value
fiber_transfer(mrb_state *mrb, mrb_value self)
{
  struct mrb_context *c = fiber_check(mrb, self);
  mrb_value* a;
  mrb_int len;

  fiber_check_cfunc(mrb, mrb->c);
  mrb_get_args(mrb, "*", &a, &len);

  if (c == mrb->root_c) {
    mrb->c->status = MRB_FIBER_TRANSFERRED;
    mrb->c = c;
    c->status = MRB_FIBER_RUNNING;
    MARK_CONTEXT_MODIFY(c);
    mrb_write_barrier(mrb, (struct RBasic*)c->fib);
    return fiber_result(mrb, a, len);
  }

  if (c == mrb->c) {
    return fiber_result(mrb, a, len);
  }

  return fiber_switch(mrb, self, len, a, FALSE, FALSE);
}
Exemplo n.º 6
0
mrb_value
mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);
  mrb_value *vals;
  int len;

  mrb_get_args(mrb, "*", &vals, &len);
  if ((a->flags & MRB_ARY_SHARED)
      && a->aux.shared->refcnt == 1 /* shared only referenced from this array */
      && a->ptr - a->aux.shared->ptr >= len) /* there's room for unshifted item */ {
    a->ptr -= len;
  }
  else {
    ary_modify(mrb, a);
    if (len == 0) return self;
    if (a->aux.capa < a->len + len)
      ary_expand_capa(mrb, a, a->len + len);
    memmove(a->ptr + len, a->ptr, sizeof(mrb_value)*a->len);
  }
  memcpy(a->ptr, vals, sizeof(mrb_value)*len);
  a->len += len;
  mrb_write_barrier(mrb, (struct RBasic*)a);

  return self;
}
Exemplo n.º 7
0
static mrb_value
fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mrb_bool resume)
{
  struct mrb_context *c = fiber_check(mrb, self);
  mrb_callinfo *ci;

  for (ci = c->ci; ci >= c->cibase; ci--) {
    if (ci->acc < 0) {
      mrb_raise(mrb, E_FIBER_ERROR, "can't cross C function boundary");
    }
  }
  if (resume && c->status == MRB_FIBER_TRANSFERRED) {
    mrb_raise(mrb, E_FIBER_ERROR, "resuming transfered fiber");
  }
  if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMING) {
    mrb_raise(mrb, E_FIBER_ERROR, "double resume");
  }
  if (c->status == MRB_FIBER_TERMINATED) {
    mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
  }
  mrb->c->status = resume ? MRB_FIBER_RESUMING : MRB_FIBER_TRANSFERRED;
  c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
  if (c->status == MRB_FIBER_CREATED) {
    mrb_value *b = c->stack+1;
    mrb_value *e = b + len;

    while (b<e) {
      *b++ = *a++;
    }
    c->cibase->argc = len;
    if (c->prev->fib)
      mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib);
    mrb_write_barrier(mrb, (struct RBasic*)c->fib);
    c->status = MRB_FIBER_RUNNING;
    mrb->c = c;

    MARK_CONTEXT_MODIFY(c);
    return c->ci->proc->env->stack[0];
  }
  MARK_CONTEXT_MODIFY(c);
  if (c->prev->fib)
    mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib);
  mrb_write_barrier(mrb, (struct RBasic*)c->fib);
  c->status = MRB_FIBER_RUNNING;
  mrb->c = c;
  return fiber_result(mrb, a, len);
}
Exemplo n.º 8
0
MRB_API void
mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
{
  struct RClass * cls = c;

  while (c) {
    if (c->iv) {
      iv_tbl *t = c->iv;

      if (iv_get(mrb, t, sym, NULL)) {
        mrb_write_barrier(mrb, (struct RBasic*)c);
        iv_put(mrb, t, sym, v);
        return;
      }
    }
    c = c->super;
  }

  if (cls && cls->tt == MRB_TT_SCLASS) {
    mrb_value klass;

    klass = mrb_obj_iv_get(mrb, (struct RObject*)cls,
                           mrb_intern_lit(mrb, "__attached__"));
    switch (mrb_type(klass)) {
    case MRB_TT_CLASS:
    case MRB_TT_MODULE:
    case MRB_TT_SCLASS:
      c = mrb_class_ptr(klass);
      break;
    default:
      c = cls;
      break;
    }
  }
  else{
    c = cls;
  }

  if (!c->iv) {
    c->iv = iv_new(mrb);
  }

  mrb_write_barrier(mrb, (struct RBasic*)c);
  iv_put(mrb, c->iv, sym, v);
}
Exemplo n.º 9
0
Arquivo: vm.c Projeto: kstephens/mruby
static void
uvset(mrb_state *mrb, int up, int idx, mrb_value v)
{
  struct REnv *e = uvenv(mrb, up);

  if (!e) return;
  e->stack[idx] = v;
  mrb_write_barrier(mrb, (struct RBasic*)e);
}
Exemplo n.º 10
0
static void
mrb_struct_modify(mrb_state *mrb, mrb_value strct)
{
  if (MRB_FROZEN_P(mrb_basic_ptr(strct))) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen struct");
  }

  mrb_write_barrier(mrb, mrb_basic_ptr(strct));
}
Exemplo n.º 11
0
static void
ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, mrb_int len)
{
  ary_modify(mrb, a);
  if (ARY_CAPA(a) < len)
    ary_expand_capa(mrb, a, len);
  array_copy(ARY_PTR(a), argv, len);
  mrb_write_barrier(mrb, (struct RBasic*)a);
  ARY_SET_LEN(a, len);
}
Exemplo n.º 12
0
static void
ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, int len)
{
  ary_modify(mrb, a);
  if (a->aux.capa < len)
    ary_expand_capa(mrb, a, len);
  memcpy(a->ptr, argv, sizeof(mrb_value)*len);
  mrb_write_barrier(mrb, (struct RBasic*)a);
  a->len = len;
}
Exemplo n.º 13
0
static void
ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, int blen)
{
  int len = a->len + blen;

  ary_modify(mrb, a);
  if (a->aux.capa < len) ary_expand_capa(mrb, a, len);
  memcpy(a->ptr+a->len, ptr, sizeof(mrb_value)*blen);
  mrb_write_barrier(mrb, (struct RBasic*)a);
  a->len = len;
}
Exemplo n.º 14
0
void
mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) /* mrb_ary_push */
{
  struct RArray *a = mrb_ary_ptr(ary);

  ary_modify(mrb, a);
  if (a->len == a->aux.capa)
    ary_expand_capa(mrb, a, a->len + 1);
  a->ptr[a->len++] = elem;
  mrb_write_barrier(mrb, (struct RBasic*)a);
}
Exemplo n.º 15
0
void
mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
{
    iv_tbl *t = obj->iv;

    if (!t) {
        t = obj->iv = iv_new(mrb);
    }
    mrb_write_barrier(mrb, (struct RBasic*)obj);
    iv_put(mrb, t, sym, v);
}
Exemplo n.º 16
0
Arquivo: array.c Projeto: iij/mruby
static void
ary_replace(mrb_state *mrb, struct RArray *a, struct RArray *b)
{
  mrb_int len = ARY_LEN(b);

  ary_modify_check(mrb, a);
  if (a == b) return;
  if (ARY_SHARED_P(a)) {
    mrb_ary_decref(mrb, a->as.heap.aux.shared);
    a->as.heap.aux.capa = 0;
    a->as.heap.len = 0;
    a->as.heap.ptr = NULL;
    ARY_UNSET_SHARED_FLAG(a);
  }
  if (ARY_SHARED_P(b)) {
  shared_b:
    if (ARY_EMBED_P(a)) {
      ARY_UNSET_EMBED_FLAG(a);
    }
    else {
      mrb_free(mrb, a->as.heap.ptr);
    }
    a->as.heap.ptr = b->as.heap.ptr;
    a->as.heap.len = len;
    a->as.heap.aux.shared = b->as.heap.aux.shared;
    a->as.heap.aux.shared->refcnt++;
    ARY_SET_SHARED_FLAG(a);
    mrb_write_barrier(mrb, (struct RBasic*)a);
    return;
  }
  if (!MRB_FROZEN_P(b) && len > ARY_REPLACE_SHARED_MIN) {
    ary_make_shared(mrb, b);
    goto shared_b;
  }
  if (ARY_CAPA(a) < len)
    ary_expand_capa(mrb, a, len);
  array_copy(ARY_PTR(a), ARY_PTR(b), len);
  mrb_write_barrier(mrb, (struct RBasic*)a);
  ARY_SET_LEN(a, len);
}
Exemplo n.º 17
0
MRB_API void
mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
{
  iv_tbl *t = obj->iv;

  if (MRB_FROZEN_P(obj)) {
    mrb_raisef(mrb, E_RUNTIME_ERROR, "can't modify frozen %S", mrb_obj_value(obj));
  }
  if (!t) {
    t = obj->iv = iv_new(mrb);
  }
  mrb_write_barrier(mrb, (struct RBasic*)obj);
  iv_put(mrb, t, sym, v);
}
Exemplo n.º 18
0
void
mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
{
    iv_tbl *t = obj->iv;

    if (!t) {
        t = obj->iv = iv_new(mrb);
    }
    else if (iv_get(mrb, t, sym, &v)) {
        return;
    }
    mrb_write_barrier(mrb, (struct RBasic*)obj);
    iv_put(mrb, t, sym, v);
}
Exemplo n.º 19
0
MRB_API void
mrb_iv_copy(mrb_state *mrb, mrb_value dest, mrb_value src)
{
  struct RObject *d = mrb_obj_ptr(dest);
  struct RObject *s = mrb_obj_ptr(src);

  if (d->iv) {
    iv_free(mrb, d->iv);
    d->iv = 0;
  }
  if (s->iv) {
    mrb_write_barrier(mrb, (struct RBasic*)d);
    d->iv = iv_copy(mrb, s->iv);
  }
}
Exemplo n.º 20
0
MRB_API void
mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
{
  iv_tbl *t;

  if (MRB_FROZEN_P(obj)) {
    mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %S", mrb_obj_value(obj));
  }
  assign_class_name(mrb, obj, sym, v);
  if (!obj->iv) {
    obj->iv = iv_new(mrb);
  }
  t = obj->iv;
  iv_put(mrb, t, sym, v);
  mrb_write_barrier(mrb, (struct RBasic*)obj);
}
Exemplo n.º 21
0
Arquivo: fiber.c Projeto: ASnow/mruby
static mrb_value
fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mrb_bool resume, mrb_bool vmexec)
{
  struct mrb_context *c = fiber_check(mrb, self);
  struct mrb_context *old_c = mrb->c;
  mrb_value value;

  fiber_check_cfunc(mrb, c);
  if (resume && c->status == MRB_FIBER_TRANSFERRED) {
    mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
  }
  if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMED) {
    mrb_raise(mrb, E_FIBER_ERROR, "double resume (fib)");
  }
  if (c->status == MRB_FIBER_TERMINATED) {
    mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
  }
  mrb->c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
  c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
  if (c->status == MRB_FIBER_CREATED) {
    mrb_value *b = c->stack+1;
    mrb_value *e = b + len;

    while (b<e) {
      *b++ = *a++;
    }
    c->cibase->argc = len;
    value = c->stack[0] = c->ci->proc->env->stack[0];
  }
  else {
    value = fiber_result(mrb, a, len);
  }
  mrb_write_barrier(mrb, (struct RBasic*)c->fib);
  c->status = MRB_FIBER_RUNNING;
  mrb->c = c;

  if (vmexec) {
    c->vmexec = TRUE;
    value = mrb_vm_exec(mrb, c->ci[-1].proc, c->ci->pc);
    mrb->c = old_c;
  }
  else {
    MARK_CONTEXT_MODIFY(c);
  }
  return value;
}
Exemplo n.º 22
0
static void
ary_concat(mrb_state *mrb, struct RArray *a, struct RArray *a2)
{
  mrb_int len;

  if (ARY_LEN(a2) > ARY_MAX_SIZE - ARY_LEN(a)) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
  }
  len = ARY_LEN(a) + ARY_LEN(a2);

  ary_modify(mrb, a);
  if (ARY_CAPA(a) < len) {
    ary_expand_capa(mrb, a, len);
  }
  array_copy(ARY_PTR(a)+ARY_LEN(a), ARY_PTR(a2), ARY_LEN(a2));
  mrb_write_barrier(mrb, (struct RBasic*)a);
  ARY_SET_LEN(a, len);
}
Exemplo n.º 23
0
Arquivo: hash.c Projeto: Zyxwvu/mruby
void
mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) /* mrb_hash_aset */
{
  khash_t(ht) *h;
  khiter_t k;

  mrb_hash_modify(mrb, hash);
  h = RHASH_TBL(hash);

  k = kh_get(ht, h, key);
  if (k == kh_end(h)) {
    /* expand */
    k = kh_put(ht, h, KEY(key));
  }

  kh_value(h, k) = val;
  mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash));
  return;
}
Exemplo n.º 24
0
Arquivo: vm.c Projeto: mrbrdo/mruby_cc
static void
cipop(mrb_state *mrb)
{
  struct mrb_context *c = mrb->c;

  if (c->ci->env) {
    struct REnv *e = c->ci->env;
    size_t len = (size_t)MRB_ENV_STACK_LEN(e);
    mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);

    MRB_ENV_UNSHARE_STACK(e);
    if (len > 0) {
      stack_copy(p, e->stack, len);
    }
    e->stack = p;
    mrb_write_barrier(mrb, (struct RBasic *)e);
  }

  c->ci--;
}
Exemplo n.º 25
0
Arquivo: array.c Projeto: iij/mruby
static mrb_value
mrb_ary_push_m(mrb_state *mrb, mrb_value self)
{
  mrb_value *argv;
  mrb_int len, len2, alen;
  struct RArray *a;

  mrb_get_args(mrb, "*!", &argv, &alen);
  a = mrb_ary_ptr(self);
  ary_modify(mrb, a);
  len = ARY_LEN(a);
  len2 = len + alen;
  if (ARY_CAPA(a) < len2) {
    ary_expand_capa(mrb, a, len2);
  }
  array_copy(ARY_PTR(a)+len, argv, alen);
  ARY_SET_LEN(a, len2);
  mrb_write_barrier(mrb, (struct RBasic*)a);

  return self;
}
Exemplo n.º 26
0
Arquivo: fiber.c Projeto: ASnow/mruby
/* mrb_fiber_yield() must be called as `return mrb_fiber_yield(...)` */
MRB_API mrb_value
mrb_fiber_yield(mrb_state *mrb, mrb_int len, const mrb_value *a)
{
  struct mrb_context *c = mrb->c;

  if (!c->prev) {
    mrb_raise(mrb, E_FIBER_ERROR, "can't yield from root fiber");
  }

  c->prev->status = MRB_FIBER_RUNNING;
  c->status = MRB_FIBER_SUSPENDED;
  mrb->c = c->prev;
  c->prev = NULL;
  if (c->vmexec) {
    c->vmexec = FALSE;
    mrb->c->ci->acc = CI_ACC_RESUMED;
  }
  mrb_write_barrier(mrb, (struct RBasic*)c->fib);
  MARK_CONTEXT_MODIFY(mrb->c);
  return fiber_result(mrb, a, len);
}
Exemplo n.º 27
0
Arquivo: hash.c Projeto: denji/mruby
void
mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val)
{
  khash_t(ht) *h;
  khiter_t k;

  mrb_hash_modify(mrb, hash);
  h = RHASH_TBL(hash);

  if (!h) h = RHASH_TBL(hash) = kh_init(ht, mrb);
  k = kh_get(ht, mrb, h, key);
  if (k == kh_end(h)) {
    /* expand */
    int ai = mrb_gc_arena_save(mrb);
    k = kh_put(ht, mrb, h, KEY(key));
    mrb_gc_arena_restore(mrb, ai);
  }

  kh_value(h, k) = val;
  mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash));
  return;
}
Exemplo n.º 28
0
void
mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) /* rb_ary_store */
{
  struct RArray *a = mrb_ary_ptr(ary);

  ary_modify(mrb, a);
  /* range check */
  if (n < 0) {
    n += a->len;
    if (n < 0) {
      mrb_raise(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len);
    }
  }
  if (a->len <= (int)n) {
    if (a->aux.capa <= (int)n)
      ary_expand_capa(mrb, a, n + 1);
    ary_fill_with_nil(a->ptr + a->len, n + 1 - a->len);
    a->len = n + 1;
  }

  a->ptr[n] = val;
  mrb_write_barrier(mrb, (struct RBasic*)a);
}
Exemplo n.º 29
0
/* self = [1,2,3]
   item = 0
   self.unshift item
   p self #=> [0, 1, 2, 3] */
mrb_value
mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item)
{
  struct RArray *a = mrb_ary_ptr(self);

  if ((a->flags & MRB_ARY_SHARED)
      && a->aux.shared->refcnt == 1 /* shared only referenced from this array */
      && a->ptr - a->aux.shared->ptr >= 1) /* there's room for unshifted item */ {
    a->ptr--;
    a->ptr[0] = item;
  }
  else {
    ary_modify(mrb, a);
    if (a->aux.capa < a->len + 1)
      ary_expand_capa(mrb, a, a->len + 1);
    memmove(a->ptr + 1, a->ptr, sizeof(mrb_value)*a->len);
    a->ptr[0] = item;
  }
  a->len++;
  mrb_write_barrier(mrb, (struct RBasic*)a);

  return self;
}
Exemplo n.º 30
0
MRB_API mrb_value
mrb_fiber_yield(mrb_state *mrb, mrb_int len, const mrb_value *a)
{
  struct mrb_context *c = mrb->c;
  mrb_callinfo *ci;

  for (ci = c->ci; ci >= c->cibase; ci--) {
    if (ci->acc < 0) {
      mrb_raise(mrb, E_FIBER_ERROR, "can't cross C function boundary");
    }
  }
  if (!c->prev) {
    mrb_raise(mrb, E_FIBER_ERROR, "can't yield from root fiber");
  }

  c->prev->status = MRB_FIBER_RUNNING;
  c->status = MRB_FIBER_SUSPENDED;
  mrb->c = c->prev;
  c->prev = NULL;
  MARK_CONTEXT_MODIFY(mrb->c);
  mrb_write_barrier(mrb, (struct RBasic*)c->fib);
  return fiber_result(mrb, a, len);
}