Esempio n. 1
0
/* call-seq:
 *   swap_method_tables(other) -> self
 * 
 * Swap the method table of the receiver with the method table of the given
 * class or module.  If +other+ is not a class or module, raise a +TypeError+. */
static VALUE evilr_swap_method_tables(VALUE self, VALUE other) {
  struct st_table *tmp;

  evilr__check_immediate(other);
  if(BUILTIN_TYPE(other) != T_MODULE && BUILTIN_TYPE(other) != T_CLASS) {
    rb_raise(rb_eTypeError, "non-class or module used");
  }

  tmp = RCLASS_M_TBL(self);
  RCLASS(self)->m_tbl = RCLASS_M_TBL(other);
  RCLASS(other)->m_tbl = tmp;
  rb_clear_cache_by_class(self);
  rb_clear_cache_by_class(other);
  return self;
}
Esempio n. 2
0
/* call-seq:
 *   set_singleton_class(klass) -> klass
 * 
 * Makes the given +klass+ the singleton class of the receiver,
 * ignoring any existing singleton class and modules extending the receiver.
 * Modules already included in +klass+ become modules that extend the receiver.
 * If the receiver is an immediate or +klass+ is not a Class,
 * raises +TypeError+. */
static VALUE evilr_set_singleton_class(VALUE self, VALUE klass) {
  evilr__check_obj_and_class(self, klass);
  RCLASS_SET_SUPER(evilr__iclass_before_next_class(klass), rb_obj_class(self));
  rb_clear_cache_by_class(klass);
  evilr__make_singleton(self, klass);
  return klass;
}
Esempio n. 3
0
/* Walk the super chain starting with the given iclass and include
 * the modules related to each iclass into the mod such that the
 * order of the initial iclass super chain and mod's super chain are
 * the same. */
void evilr__include_iclasses(VALUE mod, VALUE iclass) {
  if (iclass && BUILTIN_TYPE(iclass) == T_ICLASS) {
    evilr__include_iclasses(mod, RCLASS_SUPER(iclass));
    rb_include_module(mod, RBASIC_KLASS(iclass));
  }
  rb_clear_cache_by_class(mod);
}
Esempio n. 4
0
/* call-seq:
 *   superclass=(klass) -> klass
 * 
 * Modifies the superclass of the current class to be the given
 * class.  Any modules included in the receiver remain included.
 * Raises +TypeError+ if klass is not a Class or if the receiver
 * and class are not compatible (where their instances use
 * different internal types). */
static VALUE evilr_superclass_e(VALUE klass, VALUE super) {
  VALUE iclass;
  evilr__check_compatible_classes(klass, super);
  iclass = evilr__iclass_before_next_class(klass);
  RCLASS_SET_SUPER(iclass, super);
  rb_clear_cache_by_class(klass);
  return super;
}
Esempio n. 5
0
static void
set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
{
    int i;
    secure_visibility(self);
    for (i = 0; i < argc; i++) {
	rb_export_method(self, rb_to_id(argv[i]), ex);
    }
    rb_clear_cache_by_class(self);
}
Esempio n. 6
0
/* If self has a singleton class, set the superclass of the
 * singleton class to the given klass, keeping all modules
 * that are included in the singleton class.  Otherwise, set the
 * object's klass to the given klass. */
void evilr__reparent_singleton_class(VALUE self, VALUE klass) {
  VALUE self_klass = RBASIC_KLASS(self);

  if (IS_SINGLETON_CLASS(self_klass)) {
    RCLASS_SET_SUPER(evilr__iclass_before_next_class(self_klass), klass);
    rb_clear_cache_by_class(self_klass);
  } else {
    RBASIC_SET_KLASS(self, klass);
  }
}
static void
set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex)
{
    int i;
    secure_visibility(self);
    for (i = 0; i < argc; i++) {
	VALUE v = argv[i];
	ID id = rb_check_id(&v);
	if (!id) {
	    rb_print_undef_str(self, v);
	}
	rb_export_method(self, id, ex);
    }
    rb_clear_cache_by_class(self);
}
Esempio n. 8
0
/* call-seq:
 *   unextend(mod) -> mod || nil
 *
 * Unextends the given module +mod+ from the receiver.  If the receiver's class includes the
 * module, does not uninclude it, so this should not affect any other objects besides the
 * receiver.  If +mod+ already extended the object, returns +mod+, otherwise returns +nil+.
 * Raises +TypeError+ if +mod+ is not a Module or if the receiver is an immediate. */
static VALUE evilr_unextend(VALUE self, VALUE mod) {
  VALUE prev, cur;

  evilr__check_immediates(self, mod);
  evilr__check_type(T_MODULE, mod);

  self = rb_singleton_class(self);
  rb_clear_cache_by_class(self);
  for (prev = self, cur = RCLASS_SUPER(self); cur && BUILTIN_TYPE(cur) != T_CLASS; prev = cur, cur = RCLASS_SUPER(cur)) {
    if (BUILTIN_TYPE(cur) == T_ICLASS && RBASIC_KLASS(cur) == mod) {
      RCLASS_SET_SUPER(prev, RCLASS_SUPER(cur));
      return mod;
    }
  }

  return Qnil;
}
Esempio n. 9
0
/* call-seq:
 *   uninclude(mod) -> mod || nil
 *
 * Unincludes the given module +mod+ from the receiver or any of the receiver's
 * ancestors.  Walks the super chain of the receiver, and if an iclass for +mod+ is
 * encountered, the super chain is modified to skip that iclass.  Returns +mod+ if
 * an iclass for mod was present in the super chain, and +nil+ otherwise. If +mod+ is
 * not a Module, a +TypeError+ is raised. */
static VALUE evilr_uninclude(VALUE klass, VALUE mod) {
  VALUE cur, prev;

  evilr__check_immediate(mod);
  evilr__check_type(T_MODULE, mod);

  for (prev = klass, cur = RCLASS_SUPER(klass); cur ; prev = cur, cur = RCLASS_SUPER(cur)) {
    if (BUILTIN_TYPE(prev) == T_CLASS) {
      rb_clear_cache_by_class(prev);
    }
    if (BUILTIN_TYPE(cur) == T_ICLASS && RBASIC_KLASS(cur) == mod) {
      RCLASS_SET_SUPER(prev, RCLASS_SUPER(cur));
      return mod;
    }
  }

  return Qnil;
}
Esempio n. 10
0
/* call-seq:
 *   include_between(mod){|p, c| } -> mod || nil
 *
 * Walks the receiver's super chain, yielding the previous and current entries in
 * the super chain at every step.  The first time the block returns +true+, +mod+ is
 * inserted into the super chain between the two values, and the method returns
 * immediately.  Raises +TypeError+ if +mod+ is not a Module.
 * If the block ever returns +true+, the return value is +mod+.  If
 * the block never returns +true+, the return value is +nil+.  On the first block call,
 * the first block argument is the receiver, and on the last block call, the last block
 * argument is +nil+. */
static VALUE evilr_include_between(VALUE klass, VALUE mod) {
  VALUE iclass, prev, cur;

  evilr__check_immediate(mod);
  evilr__check_type(T_MODULE, mod);

  /* Create ICLASS for module by inserting it and removing it.
   * If module already in super chain, will change it's position. */
  rb_include_module(klass, mod);
  iclass = evilr__iclass_matching(klass, mod);
  evilr_uninclude(klass, mod);

  for (prev = klass, cur = RCLASS_SUPER(klass); prev ; prev = cur, cur = cur ? RCLASS_SUPER(cur) : cur) {
    if (BUILTIN_TYPE(prev) == T_CLASS) {
      rb_clear_cache_by_class(prev);
    }
    if (rb_yield_values(2, INCLUDE_BETWEEN_VAL(prev), INCLUDE_BETWEEN_VAL(cur)) == Qtrue) {
      RCLASS_SET_SUPER(prev, iclass);
      RCLASS_SET_SUPER(iclass, cur);
      return mod;
    }
  }
  return Qnil;
}
Esempio n. 11
0
/* Set the superclass of self to the given klass, keeping all
 * modules that are included in the class. */
void evilr__reparent_class(VALUE self, VALUE klass) {
  RCLASS_SET_SUPER(evilr__iclass_before_next_class(self), klass);
  rb_clear_cache_by_class(self);
}
Esempio n. 12
0
VALUE rb_object_free(VALUE obj)
{
  ID id_destructor = rb_intern("__destruct__");

  /* value returned by destructor */
  VALUE destruct_value = Qnil;
  
  /* prevent freeing of immediates */
  switch (TYPE(obj)) {
  case T_NIL:
  case T_FIXNUM:
  case T_TRUE:
  case T_FALSE:
  case T_SYMBOL:
    rb_raise(rb_eTypeError, "obj_free() called for immediate value");
    break;
  }

  /* prevent freeing of *some* critical objects */
  if ((obj == rb_cObject) ||
      (obj == rb_cClass) ||
      (obj == rb_cModule) ||
      (obj == rb_cSymbol) ||
      (obj == rb_cFixnum) ||
      (obj == rb_cFloat) ||
      (obj == rb_cString) ||
      (obj == rb_cRegexp) ||
      (obj == rb_cInteger) ||
      (obj == rb_cArray) ||
      (obj == rb_cNilClass) ||
      (obj == rb_cFalseClass) ||
      (obj == rb_cTrueClass) ||
      (obj == rb_cNumeric) ||
      (obj == rb_cBignum) ||
      (obj == rb_cStruct)) 
    rb_raise(rb_eTypeError, "obj_free() called for critical object");
   
  /* run destructor (if one is defined) */
  if (rb_respond_to(obj, id_destructor))
    destruct_value = rb_funcall(obj, id_destructor, 0);

#ifdef RUBY_19
      switch (BUILTIN_TYPE(obj)) {
      case T_NIL:
      case T_FIXNUM:
      case T_TRUE:
      case T_FALSE:
        rb_bug("obj_free() called for broken object");
        break;
      }

  if (FL_TEST(obj, FL_EXIVAR)) {
    rb_free_generic_ivar((VALUE)obj);
    FL_UNSET(obj, FL_EXIVAR);
  }

  switch (BUILTIN_TYPE(obj)) {
  case T_OBJECT:
    if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) &&
        RANY(obj)->as.object.as.heap.ivptr) {
      xfree(RANY(obj)->as.object.as.heap.ivptr);
    }
    break;
  case T_MODULE:
  case T_CLASS:
    rb_clear_cache_by_class((VALUE)obj);
    rb_free_m_table(RCLASS_M_TBL(obj));
    if (RCLASS_IV_TBL(obj)) {
      st_free_table(RCLASS_IV_TBL(obj));
    }
    if (RCLASS_IV_INDEX_TBL(obj)) {
      st_free_table(RCLASS_IV_INDEX_TBL(obj));
    }
    xfree(RANY(obj)->as.klass.ptr);
    break;
  case T_STRING:
    rb_str_free(obj);
    break;
  case T_ARRAY:
    rb_ary_free(obj);
    break;
  case T_HASH:
    if (RANY(obj)->as.hash.ntbl) {
      st_free_table(RANY(obj)->as.hash.ntbl);
    }
    break;
  case T_REGEXP:
    if (RANY(obj)->as.regexp.ptr) {
      onig_free(RANY(obj)->as.regexp.ptr);
    }
    break;
  case T_DATA:
    if (DATA_PTR(obj)) {
      if (RTYPEDDATA_P(obj)) {
        RDATA(obj)->dfree = RANY(obj)->as.typeddata.type->dfree;
      }
      if ((long)RANY(obj)->as.data.dfree == -1) {
        xfree(DATA_PTR(obj));
      }
      else if (RANY(obj)->as.data.dfree) {
        make_deferred(RANY(obj));
        return 1;
      }
    }
    break;
  case T_MATCH:
    if (RANY(obj)->as.match.rmatch) {
      struct rmatch *rm = RANY(obj)->as.match.rmatch;
      onig_region_free(&rm->regs, 0);
      if (rm->char_offset)
        xfree(rm->char_offset);
      xfree(rm);
    }
    break;
  case T_FILE:
    if (RANY(obj)->as.file.fptr) {
      make_io_deferred(RANY(obj));
      return 1;
    }
    break;
  case T_RATIONAL:
  case T_COMPLEX:
    break;
  case T_ICLASS:
    /* iClass shares table with the module */
    xfree(RANY(obj)->as.klass.ptr);
    break;

  case T_FLOAT:
    break;

  case T_BIGNUM:
    if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
      xfree(RBIGNUM_DIGITS(obj));
    }
    break;
  case T_NODE:
    switch (nd_type(obj)) {
    case NODE_SCOPE:
      if (RANY(obj)->as.node.u1.tbl) {
        xfree(RANY(obj)->as.node.u1.tbl);
      }
      break;
    case NODE_ALLOCA:
      xfree(RANY(obj)->as.node.u1.node);
      break;
    }
    break;			/* no need to free iv_tbl */

  case T_STRUCT:
    if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
        RANY(obj)->as.rstruct.as.heap.ptr) {
      xfree(RANY(obj)->as.rstruct.as.heap.ptr);
    }
    break;

  default:
    rb_bug("gc_sweep(): unknown data type 0x%x(%p)",
           BUILTIN_TYPE(obj), (void*)obj);
  }

#else
  switch (BUILTIN_TYPE(obj)) {
  case T_NIL:
  case T_FIXNUM:
  case T_TRUE:
  case T_FALSE:
    rb_bug("obj_free() called for broken object");
    break;
  }

  if (FL_TEST(obj, FL_EXIVAR)) {
    rb_free_generic_ivar((VALUE)obj);
  }

  switch (BUILTIN_TYPE(obj)) {
  case T_OBJECT:
    if (RANY(obj)->as.object.iv_tbl) {
      st_free_table(RANY(obj)->as.object.iv_tbl);
    }
    break;
  case T_MODULE:
  case T_CLASS:
    rb_clear_cache_by_class((VALUE)obj);
    st_free_table(RANY(obj)->as.klass.m_tbl);
    if (RANY(obj)->as.object.iv_tbl) {
      st_free_table(RANY(obj)->as.object.iv_tbl);
    }
    break;
  case T_STRING:
    if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) {
      RUBY_CRITICAL(free(RANY(obj)->as.string.ptr));
    }
    break;
  case T_ARRAY:
    if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) {
      RUBY_CRITICAL(free(RANY(obj)->as.array.ptr));
    }
    break;
  case T_HASH:
    if (RANY(obj)->as.hash.tbl) {
      st_free_table(RANY(obj)->as.hash.tbl);
    }
    break;
  case T_REGEXP:
    if (RANY(obj)->as.regexp.ptr) {
      re_free_pattern(RANY(obj)->as.regexp.ptr);
    }
    if (RANY(obj)->as.regexp.str) {
      RUBY_CRITICAL(free(RANY(obj)->as.regexp.str));
    }
    break;
  case T_DATA:
    if (DATA_PTR(obj)) {
      if ((long)RANY(obj)->as.data.dfree == -1) {
        RUBY_CRITICAL(free(DATA_PTR(obj)));
      }
      else if (RANY(obj)->as.data.dfree) {
        make_deferred(RANY(obj));
        return 1;
      }
    }
    break;
  case T_MATCH:
    if (RANY(obj)->as.match.regs) {
      re_free_registers(RANY(obj)->as.match.regs);
      RUBY_CRITICAL(free(RANY(obj)->as.match.regs));
    }
    break;
  case T_FILE:
    if (RANY(obj)->as.file.fptr) {
      struct rb_io_t *fptr = RANY(obj)->as.file.fptr;
      make_deferred(RANY(obj));
      RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;
      RDATA(obj)->data = fptr;
      return 1;
    }
    break;
  case T_ICLASS:
    /* iClass shares table with the module */
    break;

  case T_FLOAT:
  case T_VARMAP:
  case T_BLKTAG:
    break;

  case T_BIGNUM:
    if (RANY(obj)->as.bignum.digits) {
      RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits));
    }
    break;
  case T_NODE:
    switch (nd_type(obj)) {
    case NODE_SCOPE:
      if (RANY(obj)->as.node.u1.tbl) {
        RUBY_CRITICAL(free(RANY(obj)->as.node.u1.tbl));
      }
      break;
    case NODE_ALLOCA:
      RUBY_CRITICAL(free(RANY(obj)->as.node.u1.node));
      break;
    }
    break;			/* no need to free iv_tbl */

  case T_SCOPE:
    if (RANY(obj)->as.scope.local_vars &&
        RANY(obj)->as.scope.flags != SCOPE_ALLOCA) {
      VALUE *vars = RANY(obj)->as.scope.local_vars-1;
      if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0)
        RUBY_CRITICAL(free(RANY(obj)->as.scope.local_tbl));
      if ((RANY(obj)->as.scope.flags & (SCOPE_MALLOC|SCOPE_CLONE)) == SCOPE_MALLOC)
        RUBY_CRITICAL(free(vars));
    }
    break;

  case T_STRUCT:
    if (RANY(obj)->as.rstruct.ptr) {
      RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr));
    }
    break;

  default:
    rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)",
           RANY(obj)->as.basic.flags & T_MASK, obj);
  }
#endif  

  rb_gc_force_recycle(obj);

  return destruct_value;
}