static int sumSizes (mapping_t * m, mapping_node_t * elt, void * tp) { int *t = (int *)tp; *t += (svalue_size(&elt->values[0]) + svalue_size(&elt->values[1])); *t += sizeof(mapping_node_t); return 0; }
/*-------------------------------------------------------------------------*/ mp_int data_size (object_t *ob, mp_int * pTotal) /* Compute the memory usage (modified to reflect shared data use) * of the data held by object <ob> and return it. * If the object is swapped out or has no variables, return 0. * * If <pTotal> is given, *<pTotal> is set to the raw datasize. */ { mp_int total = sizeof(p_int); /* smalloc overhead */ int i; svalue_t *svp; if (pTotal != NULL) *pTotal = 0; if (ob->flags & O_SWAPPED || !(i = ob->prog->num_variables) ) return 0; ptable = new_pointer_table(); if (!ptable) errorf("(dumpstat) Out of memory for new pointer table.\n"); for (svp = ob->variables; --i >= 0; svp++) { mp_int tmp; total += svalue_size(svp, &tmp) + sizeof (svalue_t); if (pTotal != NULL) *pTotal += tmp + sizeof(svalue_t); } free_pointer_table(ptable); return total; } /* data_size() */
int data_size P1(object_t *, ob) { int total = 0, i; if (ob->prog) { for (i = 0; i < (int) ob->prog->num_variables; i++) { total += svalue_size(&ob->variables[i]) + sizeof(svalue_t); } } return total; }
int data_size (object_t * ob) { int total = 0, i; if (ob->prog) { for (i = 0; i < ob->prog->num_variables_total; i++) { depth = 0; total += svalue_size(&ob->variables[i]) + sizeof(svalue_t); } } return total; }
/*-------------------------------------------------------------------------*/ static void svalue_size_map_filter (svalue_t *key, svalue_t *values, void *extra) /* Called for all keys in a mapping, it counts the size of the values * and returns the total in extra->num_values. */ { struct svalue_size_locals *locals; mp_int total; int i; locals = (struct svalue_size_locals*)extra; locals->composite += svalue_size(key, &total); locals->total += total; for(i = locals->num_values; --i >= 0; ) { locals->composite += svalue_size(values++, &total) + sizeof(svalue_t); locals->total += total + sizeof(svalue_t); } }
static int svalue_size (svalue_t * v) { int i, total; switch (v->type) { case T_OBJECT: case T_REAL: case T_NUMBER: return 0; case T_STRING: return (strlen(v->u.string) + 1); case T_ARRAY: case T_CLASS: if (++depth > 100) return 0; /* first svalue is stored inside the array struct */ total = sizeof(array_t) - sizeof(svalue_t); for (i = 0; i < v->u.arr->size; i++) { total += svalue_size(&v->u.arr->item[i]) + sizeof(svalue_t); } depth--; return total; case T_MAPPING: if (++depth > 100) return 0; total = sizeof(mapping_t); mapTraverse(v->u.map, sumSizes, &total); depth--; return total; case T_FUNCTION: { svalue_t tmp; tmp.type = T_ARRAY; tmp.u.arr = v->u.fp->hdr.args; if (++depth > 100) return 0; if (tmp.u.arr) total = sizeof(funptr_hdr_t) + svalue_size(&tmp); else total = sizeof(funptr_hdr_t); switch (v->u.fp->hdr.type) { case FP_EFUN: total += sizeof(efun_ptr_t); break; case FP_LOCAL | FP_NOT_BINDABLE: total += sizeof(local_ptr_t); break; case FP_SIMUL: total += sizeof(simul_ptr_t); break; case FP_FUNCTIONAL: case FP_FUNCTIONAL | FP_NOT_BINDABLE: total += sizeof(functional_t); break; } depth--; return total; } #ifndef NO_BUFFER_TYPE case T_BUFFER: /* first byte is stored inside the buffer struct */ return sizeof(buffer_t) + v->u.buf->size - 1; #endif default: //some freed value or a reference (!) to one (in all my test cases //anyway), it will be removed by reclaim_objects later, Wodan //fatal("Illegal type: %d\n", v->type); ; } /* NOTREACHED */ return 0; }
static int svalue_size P1(svalue_t *, v) { int i, total; switch (v->type) { case T_OBJECT: case T_REAL: case T_NUMBER: return 0; case T_STRING: return (int) (strlen(v->u.string) + 1); case T_ARRAY: case T_CLASS: /* first svalue is stored inside the array struct */ total = sizeof(array_t) - sizeof(svalue_t); for (i = 0, total = 0; i < v->u.arr->size; i++) { total += svalue_size(&v->u.arr->item[i]) + sizeof(svalue_t); } return total; case T_MAPPING: total = sizeof(mapping_t); mapTraverse(v->u.map, (int (*) ()) sumSizes, &total); return total; case T_FUNCTION: { svalue_t tmp; tmp.type = T_ARRAY; tmp.u.arr = v->u.fp->hdr.args; if (tmp.u.arr) total = (int)(sizeof(funptr_hdr_t) + svalue_size(&tmp)); else total = (int)(sizeof(funptr_hdr_t)); switch (v->u.fp->hdr.type) { case FP_EFUN: total += sizeof(efun_ptr_t); break; case FP_LOCAL | FP_NOT_BINDABLE: total += sizeof(local_ptr_t); break; case FP_SIMUL: total += sizeof(simul_ptr_t); break; case FP_FUNCTIONAL: case FP_FUNCTIONAL | FP_NOT_BINDABLE: total += sizeof(functional_t); break; } return total; } case T_BUFFER: /* first byte is stored inside the buffer struct */ return (int) (sizeof(buffer_t) + v->u.buf->size - 1); case T_ANY: break; default: fatal("Illegal type: %d\n", v->type); } /* NOTREACHED */ return 0; }
static int sumSizes P3(mapping_t *, m, mapping_node_t *, elt, int *, t) { *t += (svalue_size(&elt->values[0]) + svalue_size(&elt->values[1])); *t += sizeof(mapping_node_t); return 0; }
/*-------------------------------------------------------------------------*/ static size_t svalue_size (svalue_t *v, mp_int * pTotal) /* Compute the memory usage of *<v> (modified to reflect data sharing), * calling svalue_size() recursively if necessary, and return it. * The size of *v itself is not included. * *<pUnshared> and *<pShared> are set to the total unshared and shared * datasize. */ { mp_int i, composite, total, overhead; assert_stack_gap(); *pTotal = 0; total = overhead = composite = 0; switch(v->type) { case T_OBJECT: case T_NUMBER: case T_FLOAT: return 0; case T_STRING: case T_SYMBOL: // If ref==0 the string is probably shared a lot, but we can't estimate // the correct number, so we return 0 as memory consumption for the // string. if (v->u.str->info.ref) { *pTotal = mstr_mem_size(v->u.str); return *pTotal / v->u.str->info.ref; } else return 0; case T_MAPPING: { struct svalue_size_locals locals; if (NULL == register_pointer(ptable, v->u.map) ) return 0; if (v->u.map->ref) { overhead = (mp_uint)mapping_overhead(v->u.map); locals.total = 0; locals.composite = 0; locals.num_values = v->u.map->num_values; walk_mapping(v->u.map, svalue_size_map_filter, &locals); *pTotal = locals.total + overhead; return (overhead + locals.composite) / v->u.map->ref; } else return 0; } case T_POINTER: case T_QUOTED_ARRAY: { if (v->u.vec == &null_vector) return 0; if (NULL == register_pointer(ptable, v->u.vec) ) return 0; if (v->u.vec->ref) { overhead = sizeof *v->u.vec - sizeof v->u.vec->item + sizeof(svalue_t) * v->u.vec->size + sizeof(char *); for (i=0; i < (mp_int)VEC_SIZE(v->u.vec); i++) { composite += svalue_size(&v->u.vec->item[i], &total); *pTotal += total; } *pTotal += overhead; return (overhead + composite) / v->u.vec->ref; } else return 0; } case T_STRUCT: { struct_t *st = v->u.strct; if (NULL == register_pointer(ptable, st) ) return 0; if (st->ref) { overhead = sizeof *st - sizeof st->member + sizeof(svalue_t) * struct_size(st); for (i=0; i < (mp_int)struct_size(st); i++) { composite += svalue_size(&st->member[i], &total); *pTotal += total; } *pTotal += overhead; return (overhead + composite) / st->ref; } else return 0; } case T_CLOSURE: { int num_values; svalue_t *svp; lambda_t *l; if (!CLOSURE_MALLOCED(v->x.closure_type)) return 0; if (!CLOSURE_REFERENCES_CODE(v->x.closure_type)) { if (v->x.closure_type == CLOSURE_LFUN) composite = SIZEOF_LAMBDA(v->u.lambda->function.lfun.context_size); else /* CLOSURE_IDENTIFIER || CLOSURE_PRELIMINARY */ composite = sizeof *v->u.lambda; composite += sizeof(char *); *pTotal = composite; return composite / v->u.lambda->ref; } /* CLOSURE_LAMBDA */ composite = overhead = 0; l = v->u.lambda; if (v->x.closure_type == CLOSURE_BOUND_LAMBDA) { total = sizeof *l - sizeof l->function + sizeof l->function.lambda; *pTotal += total; composite += total / l->ref; l = l->function.lambda; } num_values = l->function.code.num_values; svp = (svalue_t *)l - num_values; if (NULL == register_pointer(ptable, svp)) return 0; overhead = sizeof(svalue_t) * num_values + sizeof (char *); { bytecode_p p = l->function.code.program; do { switch(GET_CODE(p++)) { case F_RETURN: case F_RETURN0: break; default: continue; } break; } while (1); overhead += (p - (bytecode_p)l + (sizeof(bytecode_p) - 1)) & ~(sizeof(bytecode_p) - 1); } while (--num_values >= 0) { composite += svalue_size(svp++, &total); *pTotal += total; } *pTotal += overhead; if (l->ref) return (overhead + composite) / l->ref; else return 0; } default: fatal("Illegal type: %d\n", v->type); } /*NOTREACHED*/ return 0; }