void method_key(prof_method_key_t* key, VALUE klass, ID mid) { /* Is this an include for a module? If so get the actual module class since we want to combine all profiling results for that module. */ if (klass != 0) klass = (BUILTIN_TYPE(klass) == T_ICLASS ? RBASIC(klass)->klass : klass); key->klass = klass; key->mid = mid; key->key = (klass << 4) + (mid << 2); }
VALUE rb_mod_included_modules(VALUE mod) { VALUE ary = rb_ary_new(); VALUE p; for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { if (BUILTIN_TYPE(p) == T_ICLASS) { rb_ary_push(ary, RBASIC(p)->klass); } } return ary; }
VALUE rb_mod_include_p(VALUE mod, VALUE mod2) { VALUE p; Check_Type(mod2, T_MODULE); for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { if (BUILTIN_TYPE(p) == T_ICLASS) { if (RBASIC(p)->klass == mod2) return Qtrue; } } return Qfalse; }
static int cos_i(void *vstart, void *vend, size_t stride, void *data) { size_t *counts = (size_t *)data; VALUE v = (VALUE)vstart; for (;v != (VALUE)vend; v += stride) { if (RBASIC(v)->flags) { counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v); } } return 0; }
static int linear_object_p(VALUE obj) { if (FIXNUM_P(obj) || FLONUM_P(obj)) return TRUE; if (SPECIAL_CONST_P(obj)) return FALSE; switch (BUILTIN_TYPE(obj)) { case T_FLOAT: case T_BIGNUM: return TRUE; } if (rb_obj_is_kind_of(obj, rb_cNumeric)) return TRUE; if (rb_obj_is_kind_of(obj, rb_cTime)) return TRUE; return FALSE; }
void rb_cmperr(VALUE x, VALUE y) { VALUE classname; if (SPECIAL_CONST_P(y) || BUILTIN_TYPE(y) == T_FLOAT) { classname = rb_inspect(y); } else { classname = rb_obj_class(y); } rb_raise(rb_eArgError, "comparison of %"PRIsVALUE" with %"PRIsVALUE" failed", rb_obj_class(x), classname); }
static int include_modules_at(const VALUE klass, VALUE c, VALUE module) { VALUE p; int changed = 0; const st_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass)); while (module) { int superclass_seen = FALSE; if (RCLASS_ORIGIN(module) != module) goto skip; if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module)) return -1; /* ignore if the module included already in superclasses */ for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { switch (BUILTIN_TYPE(p)) { case T_ICLASS: if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { if (!superclass_seen) { c = p; /* move insertion point */ } goto skip; } break; case T_CLASS: superclass_seen = TRUE; break; } } c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c))); if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) { VALUE refined_class = rb_refinement_module_get_refined_class(klass); st_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i, (st_data_t) refined_class); FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT); } if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) changed = 1; if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries) changed = 1; skip: module = RCLASS_SUPER(module); } return changed; }
static inline int enc_capable(VALUE obj) { if (SPECIAL_CONST_P(obj)) return SYMBOL_P(obj); switch (BUILTIN_TYPE(obj)) { case T_STRING: case T_REGEXP: case T_FILE: return TRUE; case T_DATA: if (is_data_encoding(obj)) return TRUE; default: return FALSE; } }
void rb_cmperr(VALUE x, VALUE y) { const char *classname; if (SPECIAL_CONST_P(y) || BUILTIN_TYPE(y) == T_FLOAT) { y = rb_inspect(y); classname = StringValuePtr(y); } else { classname = rb_obj_classname(y); } rb_raise(rb_eArgError, "comparison of %s with %s failed", rb_obj_classname(x), classname); }
static int cn_i(void *vstart, void *vend, size_t stride, void *n) { size_t *nodes = (size_t *)n; VALUE v = (VALUE)vstart; for (; v != (VALUE)vend; v += stride) { if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_NODE) { size_t s = nd_type((NODE *)v); nodes[s]++; } } return 0; }
VALUE rb_mod_ancestors(VALUE mod) { VALUE p, ary = rb_ary_new(); for (p = mod; p; p = RCLASS_SUPER(p)) { if (BUILTIN_TYPE(p) == T_ICLASS) { rb_ary_push(ary, RBASIC(p)->klass); } else if (p == RCLASS_ORIGIN(p)) { rb_ary_push(ary, p); } } return ary; }
VALUE rb_mod_included_modules(VALUE mod) { VALUE ary = rb_ary_new(); VALUE p; VALUE origin = RCLASS_ORIGIN(mod); for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) { VALUE m = RBASIC(p)->klass; if (RB_TYPE_P(m, T_MODULE)) rb_ary_push(ary, m); } } return ary; }
static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) { if (str == Qnil) return; assert(BUILTIN_TYPE(str) == RUBY_T_STRING); upb_sink subsink; // Ensure that the string has the correct encoding. We also check at field-set // time, but the user may have mutated the string object since then. native_slot_validate_string_encoding(upb_fielddef_type(f), str); upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str), &subsink); upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str), RSTRING_LEN(str), NULL); upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR)); }
VALUE rb_mod_ancestors(VALUE mod) { VALUE p, ary = rb_ary_new(); for (p = mod; p; p = RCLASS_SUPER(p)) { if (FL_TEST(p, FL_SINGLETON)) continue; if (BUILTIN_TYPE(p) == T_ICLASS) { rb_ary_push(ary, RBASIC(p)->klass); } else { rb_ary_push(ary, p); } } return ary; }
void rb_include_module(VALUE klass, VALUE module) { VALUE p, c; int changed = 0; rb_frozen_class_p(klass); if (!OBJ_UNTRUSTED(klass)) { rb_secure(4); } if (TYPE(module) != T_MODULE) { Check_Type(module, T_MODULE); } OBJ_INFECT(klass, module); c = klass; while (module) { int superclass_seen = FALSE; if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module)) rb_raise(rb_eArgError, "cyclic include detected"); /* ignore if the module included already in superclasses */ for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { switch (BUILTIN_TYPE(p)) { case T_ICLASS: if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { if (!superclass_seen) { c = p; /* move insertion point */ } goto skip; } break; case T_CLASS: superclass_seen = TRUE; break; } } c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c)); if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) changed = 1; skip: module = RCLASS_SUPER(module); } if (changed) rb_clear_cache(); }
/* * call-seq: * remove_features(mod) => mod * * When this module is unincluded from another, Ruby Internal calls * remove_features in this module. The default behavior is to remove * the constants, methods, and module variables of this module from * _mod_. If this module has not been included by _mod_, an exception * will be raised. */ static VALUE module_remove_features(VALUE module, VALUE uninclude) { VALUE prev, mod; if(TYPE(uninclude) != T_CLASS && TYPE(uninclude) != T_MODULE) { Check_Type(uninclude, T_CLASS); } rb_frozen_class_p(uninclude); if(!OBJ_TAINTED(uninclude)) { rb_secure(4); } OBJ_INFECT(uninclude, module); if(RCLASS(uninclude)->m_tbl == RCLASS(module)->m_tbl) { rb_raise(rb_eArgError, "Cannot remove module from itself"); } prev = uninclude; mod = RCLASS_SUPER(uninclude); while(mod) { if(RCLASS(module)->m_tbl == RCLASS(mod)->m_tbl) { RCLASS_SUPER(prev) = RCLASS_SUPER(mod); rb_clear_cache(); return module; } if(BUILTIN_TYPE(mod) == T_CLASS) { break; } prev = mod; mod = RCLASS_SUPER(mod); } rb_raise(rb_eArgError, "Could not find included module"); return module; }
/* a modified version of include_class_new from class.c */ static VALUE j_class_new(VALUE module, VALUE sup) { #ifdef RUBY_19 VALUE klass = class_alloc(T_ICLASS, rb_cClass); #else NEWOBJ(klass, struct RClass); OBJSETUP(klass, rb_cClass, T_ICLASS); #endif if (BUILTIN_TYPE(module) == T_ICLASS) { module = KLASS_OF(module); } if (!RCLASS_IV_TBL(module)) { RCLASS_IV_TBL(module) = (struct st_table *)st_init_numtable(); } /* assign iv_tbl, m_tbl and super */ RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); RCLASS_SUPER(klass) = sup; if(TYPE(module) != T_OBJECT) { RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); } else { RCLASS_M_TBL(klass) = RCLASS_M_TBL(CLASS_OF(module)); } /* */ if (TYPE(module) == T_ICLASS) { KLASS_OF(klass) = KLASS_OF(module); } else { KLASS_OF(klass) = module; } if(TYPE(module) != T_OBJECT) { OBJ_INFECT(klass, module); OBJ_INFECT(klass, sup); } return (VALUE)klass; }
static inline VALUE invoke_block_from_c(rb_thread_t *th, const rb_block_t *block, VALUE self, int argc, const VALUE *argv, const rb_block_t *blockptr, const NODE *cref) { if (SPECIAL_CONST_P(block->iseq)) return Qnil; else if (BUILTIN_TYPE(block->iseq) != T_NODE) { const rb_iseq_t *iseq = block->iseq; const rb_control_frame_t *cfp; rb_control_frame_t *ncfp; int i, opt_pc, arg_size = iseq->arg_size; int type = block_proc_is_lambda(block->proc) ? VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK; rb_vm_set_finish_env(th); cfp = th->cfp; CHECK_STACK_OVERFLOW(cfp, argc + iseq->stack_max); for (i=0; i<argc; i++) { cfp->sp[i] = argv[i]; } opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, blockptr, type == VM_FRAME_MAGIC_LAMBDA); ncfp = vm_push_frame(th, iseq, type, self, GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp, iseq->local_size - arg_size); ncfp->me = th->passed_me; th->passed_me = 0; th->passed_block = blockptr; if (cref) { th->cfp->dfp[-1] = (VALUE)cref; } return vm_exec(th); } else { return vm_yield_with_cfunc(th, block, self, argc, argv, blockptr); } }
void rb_include_module(VALUE klass, VALUE module) { VALUE p, c; int changed = 0; rb_frozen_class_p(klass); if (!OBJ_TAINTED(klass)) { rb_secure(4); } if (TYPE(module) != T_MODULE) { Check_Type(module, T_MODULE); } OBJ_INFECT(klass, module); c = klass; while (module) { int superclass_seen = Qfalse; if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl) rb_raise(rb_eArgError, "cyclic include detected"); /* ignore if the module included already in superclasses */ for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) { switch (BUILTIN_TYPE(p)) { case T_ICLASS: if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) { if (!superclass_seen) { c = p; /* move insertion point */ } goto skip; } break; case T_CLASS: superclass_seen = Qtrue; break; } } c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super); changed = 1; skip: module = RCLASS(module)->super; } if (changed) rb_clear_cache(); }
VALUE rb_singleton_class(VALUE obj) { VALUE klass; ID attached; if (FIXNUM_P(obj) || SYMBOL_P(obj)) { rb_raise(rb_eTypeError, "can't define singleton"); } if (rb_special_const_p(obj)) { SPECIAL_SINGLETON(Qnil, rb_cNilClass); SPECIAL_SINGLETON(Qfalse, rb_cFalseClass); SPECIAL_SINGLETON(Qtrue, rb_cTrueClass); rb_bug("unknown immediate %ld", obj); } CONST_ID(attached, "__attached__"); if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) && rb_ivar_get(RBASIC(obj)->klass, attached) == obj) { klass = RBASIC(obj)->klass; } else { klass = rb_make_metaclass(obj, RBASIC(obj)->klass); } if (BUILTIN_TYPE(obj) == T_CLASS) { if (rb_iv_get(RBASIC(klass)->klass, "__attached__") != klass) make_metametaclass(klass); } if (OBJ_TAINTED(obj)) { OBJ_TAINT(klass); } else { FL_UNSET(klass, FL_TAINT); } if (OBJ_UNTRUSTED(obj)) { OBJ_UNTRUST(klass); } else { FL_UNSET(klass, FL_UNTRUSTED); } if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass); return klass; }
/* call-seq: * swap(other) -> self * * Swap the contents of the receiver with +other+: * * a = [] * b = {} * a.swap(b) # => {} * a # => {} * b # => [] * * You cannot swap a Class or Module except with another * Class or Module, and you can only swap a Class with a Class and * a Module with a Module (no swapping a Class with Module), and you * cannot swap immediate values. If an invalid swap attempt is * detected, a +TypeError+ is raised.*/ static VALUE evilr_swap(VALUE self, VALUE other) { char tmp[OBJECT_SIZE]; evilr__check_immediates(self, other); if ((BUILTIN_TYPE(self) == T_MODULE || BUILTIN_TYPE(self) == T_CLASS || BUILTIN_TYPE(other) == T_MODULE || BUILTIN_TYPE(other) == T_CLASS) && BUILTIN_TYPE(self) != BUILTIN_TYPE(other)) { rb_raise(rb_eTypeError, "incompatible types used"); } memcpy(tmp, ROBJECT(self), OBJECT_SIZE); memcpy(ROBJECT(self), ROBJECT(other), OBJECT_SIZE); memcpy(ROBJECT(other), tmp, OBJECT_SIZE); return self; }
/* * search method entry without the method cache. * * if you need method entry with method cache (normal case), use * rb_method_entry() simply. */ rb_method_entry_t * rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *defined_class_ptr) { VALUE defined_class; rb_method_entry_t *me = search_method(klass, id, &defined_class); if (me && me->klass) { switch (BUILTIN_TYPE(me->klass)) { case T_CLASS: if (RBASIC(klass)->flags & FL_SINGLETON) break; /* fall through */ case T_ICLASS: defined_class = me->klass; } } if (ruby_running) { if (OPT_GLOBAL_METHOD_CACHE) { struct cache_entry *ent; ent = GLOBAL_METHOD_CACHE(klass, id); ent->class_serial = RCLASS_SERIAL(klass); ent->method_state = GET_GLOBAL_METHOD_STATE(); ent->defined_class = defined_class; ent->mid = id; if (UNDEFINED_METHOD_ENTRY_P(me)) { ent->me = 0; me = 0; } else { ent->me = me; } } else if (UNDEFINED_METHOD_ENTRY_P(me)) { me = 0; } } if (defined_class_ptr) *defined_class_ptr = defined_class; return me; }
/* call-seq: * evilr_debug_print -> nil * * Prints to stdout the receiver and all entries in the receiver's klass's super chain, * using the pointers of the current entry, it's klass, iv_tbl, m_tbl, and super entry, * as well as the entry's flags. If Class or Module is given, uses their * super chain, not the super chain of their klass. If the receiver is an immediate value, * a +TypeError+ is raised. */ static VALUE evilr_debug_print(VALUE self) { if (self == NULL) { return Qnil; } evilr__check_immediate(self); switch(BUILTIN_TYPE(self)) { case T_CLASS: case T_ICLASS: case T_MODULE: printf("self %p klass %p flags 0x%lx iv_tbl %p m_tbl %p super %p\n", (void *)self, (void *)RBASIC_KLASS(self), RBASIC_FLAGS(self), (void *)RCLASS_IV_TBL(self), (void *)RCLASS_M_TBL(self), (void *)RCLASS_SUPER(self)); self = RCLASS_SUPER(self); break; default: printf("self %p klass %p flags 0x%lx iv_tbl/ptr %p\n", (void *)self, (void *)RBASIC_KLASS(self), RBASIC_FLAGS(self), (void *)ROBJECT_IVPTR(self)); self = RBASIC_KLASS(self); break; } return evilr_debug_print(self); }
static VALUE proc_arity(VALUE self) { rb_proc_t *proc; rb_iseq_t *iseq; GetProcPtr(self, proc); iseq = proc->block.iseq; if (iseq && BUILTIN_TYPE(iseq) != T_NODE) { if (iseq->arg_rest == 0 && iseq->arg_opts == 0) { return INT2FIX(iseq->argc); } else { return INT2FIX(-iseq->argc - 1); } } else { return INT2FIX(-1); } }
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type) { const char *etype; static const char mesg[] = "wrong argument type %s (expected %s)"; if (SPECIAL_CONST_P(obj) || BUILTIN_TYPE(obj) != T_DATA) { Check_Type(obj, T_DATA); } if (!RTYPEDDATA_P(obj)) { etype = rb_obj_classname(obj); rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name); } else if (RTYPEDDATA_TYPE(obj) != data_type) { etype = RTYPEDDATA_TYPE(obj)->wrap_struct_name; rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name); } return DATA_PTR(obj); }
static int cs_i(void *vstart, void *vend, size_t stride, void *n) { struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n; VALUE v = (VALUE)vstart; for (; v != (VALUE)vend; v += stride) { if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_SYMBOL) { ID id = RSYMBOL(v)->id; if ((id & ~ID_SCOPE_MASK) == 0) { counts->mortal++; } else { counts->immortal++; } } } return 0; }
VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach) { VALUE klass = RBASIC(obj)->klass; if (!FL_TEST(klass, FL_SINGLETON)) return klass; else { /* copy singleton(unnamed) class */ VALUE clone = class_alloc(RBASIC(klass)->flags, 0); if (BUILTIN_TYPE(obj) == T_CLASS) { RBASIC_SET_CLASS(clone, clone); } else { RBASIC_SET_CLASS(clone, rb_singleton_class_clone(klass)); } RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass)); RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator; if (RCLASS_IV_TBL(klass)) { RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(klass)); } if (RCLASS_CONST_TBL(klass)) { struct clone_const_arg arg; RCLASS_CONST_TBL(clone) = st_init_numtable(); arg.klass = clone; arg.tbl = RCLASS_CONST_TBL(clone); st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)&arg); } if (attach != Qundef) { rb_singleton_class_attached(clone, attach); } RCLASS_M_TBL_INIT(clone); st_foreach(RCLASS_M_TBL(klass), clone_method_i, (st_data_t)clone); rb_singleton_class_attached(RBASIC(clone)->klass, clone); FL_SET(clone, FL_SINGLETON); return clone; } }
static int cto_i(void *vstart, void *vend, size_t stride, void *data) { VALUE hash = (VALUE)data; VALUE v = (VALUE)vstart; for (; v != (VALUE)vend; v += stride) { if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_DATA) { VALUE counter = rb_hash_aref(hash, RBASIC(v)->klass); if (NIL_P(counter)) { counter = INT2FIX(1); } else { counter = INT2FIX(FIX2INT(counter) + 1); } rb_hash_aset(hash, RBASIC(v)->klass, counter); } } return 0; }
/*! * \internal * Creates a singleton class for an object. * * \note DO NOT USE the function in an extension libraries. Use rb_singleton_class. * \param obj An object. * \param super A class from which the singleton class derives. * \note \a super is ignored if \a obj is a metaclass. * \return The singleton class of the object. */ VALUE rb_make_metaclass(VALUE obj, VALUE super) { if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) { /* obj is a metaclass */ return make_metametaclass(obj); } else { VALUE metasuper; VALUE klass = rb_class_boot(super); FL_SET(klass, FL_SINGLETON); RBASIC(obj)->klass = klass; rb_singleton_class_attached(klass, obj); metasuper = RBASIC(rb_class_real(super))->klass; /* metaclass of a superclass may be NULL at boot time */ if (metasuper) { RBASIC(klass)->klass = metasuper; } return klass; } }
int rb_enc_get_index(VALUE obj) { int i = -1; VALUE tmp; if (SPECIAL_CONST_P(obj)) { if (!SYMBOL_P(obj)) return -1; obj = rb_id2str(SYM2ID(obj)); } switch (BUILTIN_TYPE(obj)) { as_default: default: case T_STRING: case T_REGEXP: i = ENCODING_GET_INLINED(obj); if (i == ENCODING_INLINE_MAX) { VALUE iv; iv = rb_ivar_get(obj, rb_id_encoding()); i = NUM2INT(iv); } break; case T_FILE: tmp = rb_funcall(obj, rb_intern("internal_encoding"), 0, 0); if (NIL_P(tmp)) obj = rb_funcall(obj, rb_intern("external_encoding"), 0, 0); else obj = tmp; if (NIL_P(obj)) break; case T_DATA: if (is_data_encoding(obj)) { i = enc_check_encoding(obj); } else { goto as_default; } break; } return i; }