static size_t vm_memsize(const void *ptr) { if (ptr) { const rb_vm_t *vmobj = ptr; return sizeof(rb_vm_t) + st_memsize(vmobj->living_threads); } else { return 0; } }
static size_t fiber_memsize(const void *ptr) { const rb_fiber_t *fib = ptr; size_t size = 0; if (ptr) { size = sizeof(*fib); if (fib->cont.type != ROOT_FIBER_CONTEXT) { size += st_memsize(fib->cont.saved_thread.local_storage); } size += cont_memsize(&fib->cont); } return 0; }
static size_t thread_memsize(const void *ptr) { if (ptr) { const rb_thread_t *th = ptr; size_t size = sizeof(rb_thread_t); if (!th->root_fiber) { size += th->stack_size * sizeof(VALUE); } if (th->local_storage) { st_memsize(th->local_storage); } return size; } else { return 0; } }
static size_t memsize_of(VALUE obj) { size_t size = 0; if (SPECIAL_CONST_P(obj)) { return 0; } if (FL_TEST(obj, FL_EXIVAR)) { size += rb_generic_ivar_memsize(obj); } switch (BUILTIN_TYPE(obj)) { case T_OBJECT: if (!(RBASIC(obj)->flags & ROBJECT_EMBED) && ROBJECT(obj)->as.heap.ivptr) { size += ROBJECT(obj)->as.heap.numiv * sizeof(VALUE); } break; case T_MODULE: case T_CLASS: size += st_memsize(RCLASS_M_TBL(obj)); if (RCLASS_IV_TBL(obj)) { size += st_memsize(RCLASS_IV_TBL(obj)); } if (RCLASS_IV_INDEX_TBL(obj)) { size += st_memsize(RCLASS_IV_INDEX_TBL(obj)); } if (RCLASS(obj)->ptr->iv_tbl) { size += st_memsize(RCLASS(obj)->ptr->iv_tbl); } if (RCLASS(obj)->ptr->const_tbl) { size += st_memsize(RCLASS(obj)->ptr->const_tbl); } size += sizeof(rb_classext_t); break; case T_STRING: size += rb_str_memsize(obj); break; case T_ARRAY: size += rb_ary_memsize(obj); break; case T_HASH: if (RHASH(obj)->ntbl) { size += st_memsize(RHASH(obj)->ntbl); } break; case T_REGEXP: if (RREGEXP(obj)->ptr) { size += onig_memsize(RREGEXP(obj)->ptr); } break; case T_DATA: size += rb_objspace_data_type_memsize(obj); break; case T_MATCH: if (RMATCH(obj)->rmatch) { struct rmatch *rm = RMATCH(obj)->rmatch; size += sizeof(struct re_registers); /* TODO: onig_region_memsize(&rm->regs); */ size += sizeof(struct rmatch_offset) * rm->char_offset_num_allocated; size += sizeof(struct rmatch); } break; case T_FILE: if (RFILE(obj)->fptr) { size += rb_io_memsize(RFILE(obj)->fptr); } break; case T_RATIONAL: case T_COMPLEX: break; case T_ICLASS: /* iClass shares table with the module */ break; case T_FLOAT: break; case T_BIGNUM: if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) { size += RBIGNUM_LEN(obj) * sizeof(BDIGIT); } break; case T_NODE: switch (nd_type(obj)) { case NODE_SCOPE: if (RNODE(obj)->u1.tbl) { /* TODO: xfree(RANY(obj)->as.node.u1.tbl); */ } break; case NODE_ALLOCA: /* TODO: xfree(RANY(obj)->as.node.u1.node); */ ; } break; /* no need to free iv_tbl */ case T_STRUCT: if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 && RSTRUCT(obj)->as.heap.ptr) { size += sizeof(VALUE) * RSTRUCT_LEN(obj); } break; case T_ZOMBIE: break; default: rb_bug("objspace/memsize_of(): unknown data type 0x%x(%p)", BUILTIN_TYPE(obj), (void*)obj); } return size; }