#include <stdio.h> #include "lint.h" #include "interpret.h" #include "object.h" #include "exec.h" #define USES_SVALUE_STRLEN #include "smalloc.h" #include "lang.h" #include "instrs.h" #if defined(AMIGA) #include "hosts/amiga/ixfile.h" #endif /* * Write statistics about objects on file. */ #ifdef MAPPINGS static int svalue_size PROT((struct svalue *)); struct svalue_size_locals { mp_int total; int num_values; }; void svalue_size_map_filter(key, values, extra) struct svalue *key; struct svalue *values; char *extra; { struct svalue_size_locals *locals; int i; locals = (struct svalue_size_locals*)extra; locals->total += svalue_size(key); for(i = locals->num_values; --i >= 0; ) { locals->total += svalue_size(values++) + sizeof(struct svalue); } } #endif extern struct object *obj_list; static int svalue_size(v) struct svalue *v; { mp_int i, total; switch(v->type) { case T_OBJECT: case T_NUMBER: #ifdef FLOATS case T_FLOAT: #endif return 0; case T_STRING: /* Include some malloc overhead. */ if (v->x.string_type == STRING_SHARED) return strlen(v->u.string) + sizeof(short) + 3*sizeof(char*) & ~(sizeof(char *) - 1); return svalue_strlen(v) + 2*sizeof(char *) & ~(sizeof(char *) - 1); case T_SYMBOL: return strlen(v->u.string) + sizeof(short) + 3*sizeof(char*) & ~(sizeof(char *) - 1); #ifdef MAPPINGS case T_MAPPING: { extern int register_pointer PROT((char *)); extern void walk_mapping PROT(( struct mapping *, void (*)(struct svalue *, struct svalue *, char *), char * )); struct svalue_size_locals locals; struct condensed_mapping *cm; if (register_pointer( (char *)(v->u.map) ) ) return 0; cm = v->u.map->condensed; locals.total = cm->string_size + cm->misc_size; locals.num_values = v->u.map->num_values; walk_mapping(v->u.map, svalue_size_map_filter, (char *)&locals); if (v->u.map->hash) locals.total += sizeof(struct hash_mapping) + v->u.map->hash->mask * sizeof(struct map_chain *) + v->u.map->hash->used * (sizeof (struct map_chain) - sizeof(struct svalue)); return locals.total; } #endif case T_POINTER: case T_QUOTED_ARRAY: { extern struct vector null_vector; extern int register_pointer PROT((char *)); if (v->u.vec == &null_vector) return 0; if (register_pointer( (char *)(v->u.vec) ) ) return 0; #ifdef MALLOC_smalloc total = malloced_size(v->u.vec) * sizeof(p_int); #else total = sizeof *v->u.vec - sizeof v->u.vec->item + sizeof(struct svalue) * v->u.vec->size + sizeof(char *); #endif for (i=0; i < v->u.vec->size; i++) { total += svalue_size(&v->u.vec->item[i]); } return total; } case T_CLOSURE: { extern int register_pointer PROT((char *)); int num_values; struct svalue *svp; struct lambda *l; if (!CLOSURE_MALLOCED(v->x.closure_type)) return 0; if (!CLOSURE_REFERENCES_CODE(v->x.closure_type)) { /* CLOSURE_LFUN || CLOSURE_IDENTIFIER || CLOSURE_PRELIMINARY */ return sizeof *v->u.lambda + sizeof(char *); } /* CLOSURE_LAMBDA */ total = 0; l = v->u.lambda; if (v->x.closure_type == CLOSURE_BOUND_LAMBDA) { total += sizeof *l - sizeof l->function + sizeof l->function.lambda; l = l->function.lambda; } num_values = EXTRACT_UCHAR(&l->function.code[0]); if (num_values == 0xff) num_values = ((struct svalue *)l)[-0xff].u.number; svp = (struct svalue *)l - num_values; if (register_pointer( (char *)svp ) ) return 0; #ifdef MALLOC_smalloc total += malloced_size(svp) * sizeof(p_int); #else total += sizeof(struct svalue) * num_values + sizeof (char *); { char *p = &l->function.code[2]; do { switch(*++p) { case F_RETURN -F_OFFSET: case F_RETURN0-F_OFFSET: break; } } while (1); total += p - (char *)l + (sizeof(char *) - 1) & ~(sizeof(char *) - 1); } #endif while (--num_values >= 0) { total += svalue_size(svp++); } return total; } default: fatal("Illegal type: %d\n", v->type); } /*NOTREACHED*/ #ifdef lint return 0; #endif } static mp_int data_size(ob) struct object *ob; { struct pointer_record; extern void init_pointer_table PROT((struct pointer_record **)); extern void free_pointer_table PROT((void)); mp_int total = 0, i; struct pointer_record *pointer_table_space[256]; init_pointer_table(pointer_table_space); if (ob->prog) { init_pointer_table(pointer_table_space); for (i = 0; i < ob->prog->num_variables; i++) total += svalue_size(&ob->variables[i]) + sizeof (struct svalue); } free_pointer_table(); return total; } void dumpstat() { FILE *f; struct object *ob; f = fopen("OBJ_DUMP", "w"); if (f == 0) return; add_message("Dumping to OBJ_DUMP ..."); for (ob = obj_list; ob; ob = ob->next_all) { mp_int tmp; if (ob->prog && (ob->prog->ref == 1 || !(ob->flags & O_CLONE))) tmp = ob->prog->total_size; else tmp = 0; fprintf(f, "%-20s %5ld ref %2d %s %s (%ld) %s\n", ob->name, tmp + data_size(ob) + sizeof (struct object), ob->ref, ob->flags & O_HEART_BEAT ? "HB" : " ", ob->super ? ob->super->name : "--",/*ob->cpu*/ 0L, ob->swap_num >=0 ? "SWAPPED" : ""); } add_message("done.\n"); fclose(f); }