|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.0 (the 'License'). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License."
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * objc-utils.m
26: * Copyright 1988, NeXT, Inc.
27: * Author: s. naroff
28: */
29: #ifdef SHLIB
30: #import "shlib.h"
31: #endif
32:
33: #import "objc-private.h"
34:
35: #include <sys/time.h>
36: #include <sys/resource.h>
37: #include <stdio.h>
38: #include <time.h>
39: #include "objc-dispatch.h"
40:
41: #import "HashTable.h"
42:
43:
44: /* Return time used so far, in microseconds. */
45:
46: int gettime (void)
47: {
48: struct rusage rusage;
49:
50: getrusage (0, &rusage);
51: return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec
52: + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec);
53: }
54:
55: void print_time (const char *str, int total, struct timeval *tv)
56: {
57: extern char **NXArgv;
58:
59: fprintf (stderr,
60: "time to `%s' for `%s':\n\t%7d.%06d (sys+usr)"
61: "\t%7ld.%01ld (real).\n", str, NXArgv[0],
62: total / 1000000, total % 1000000,
63: tv->tv_sec, tv->tv_usec/100000);
64: }
65:
66: static int cacheHits = 0;
67: static int cacheMisses = 0;
68: static int supercacheHits = 0;
69: static int supercacheMisses = 0;
70:
71: void _objc_msgCollectStats(MSG stackframe, int fromsuper, int cacheHit)
72: {
73: if (fromsuper)
74: cacheHit ? supercacheHits++ : supercacheMisses++;
75: else
76: cacheHit ? cacheHits++ : cacheMisses++;
77: }
78:
79: void _objc_msgPrintStats(void)
80: {
81: time_t tm = time(0);
82:
83: fprintf (stderr, "%s", ctime(&tm));
84: fprintf (stderr, "maxSelector: %d\n", (int) _sel_getMaxUid());
85: fprintf (stderr, " _msg: sent = %6d, %6d hits %6d misses",
86: cacheHits+cacheMisses, cacheHits,cacheMisses);
87: fprintf (stderr, " (%3.2f%%)\n",
88:
89: (float)cacheHits/(cacheHits+cacheMisses) * 100);
90: fprintf (stderr, " _msgSuper: sent = %6d, %6d hits %6d misses",
91: supercacheHits+supercacheMisses, supercacheHits,supercacheMisses);
92: fprintf (stderr, " (%3.2f%%)\n",
93: (float)supercacheHits/(supercacheHits+supercacheMisses) * 100);
94:
95: // reset
96: cacheHits = cacheMisses = supercacheHits = supercacheMisses = 0;
97: }
98:
99: int _objc_class_respondsTo(Class class)
100: {
101: Class super;
102: int nMethods = 0;
103:
104: if (class->methods) {
105: struct objc_method_list *catmethods = class->methods->method_next;
106: if (catmethods) {
107: do {
108: nMethods += catmethods->method_count;
109: catmethods = catmethods->method_next;
110: } while (catmethods);
111: } else {
112: nMethods += class->methods->method_count;
113: }
114: }
115:
116: for (super = class->super_class; super; super = super->super_class)
117: if (super->methods) {
118: struct objc_method_list *catmethods = super->methods->method_next;
119: if (catmethods) {
120: do {
121: nMethods += catmethods->method_count;
122: catmethods = catmethods->method_next;
123: } while (catmethods);
124: } else {
125: nMethods += super->methods->method_count;
126: }
127: }
128: return nMethods;
129: }
130:
131: /*
132: * Purpose: debug/analysis.
133: */
134: void _objc_classPrintStats(int detail)
135: {
136: int n_meta = 0, b_meta = 0, n_class = 0, b_class = 0;
137: int n_classes = 0, n_classes_used = 0;
138: int n_class_responds = 0, n_meta_responds = 0;
139: int class_responds = 0, meta_responds = 0;
140: int n_class_implements = 0, n_meta_implements = 0;
141: int class_implements = 0, meta_implements = 0;
142: int n_categories = 0;
143: Class cls, oldvalue;
144: NXHashTable *class_hash;
145: NXHashState state;
146: void *page;
147: HashTable *pagehash = [HashTable newKeyDesc:"i"];
148:
149: class_hash = objc_getClasses();
150: state = NXInitHashState(class_hash);
151:
152: while (NXNextHashState(class_hash, &state, (void **)&cls)) {
153:
154: Class meta = cls->isa;
155:
156: n_classes++;
157:
158: // if (CLS_GETINFO(meta, CLS_INITIALIZED))
159: {
160: if (CLS_GETINFO(meta, CLS_INITIALIZED))
161: n_classes_used++;
162:
163: page = (void *)((unsigned int)cls - ((unsigned int)cls % 0x2000));
164: oldvalue = [pagehash insertKey:page value:cls];
165:
166: if (detail)
167: printf("`%s' (%p,page #%p):\n", cls->name,
168: cls, page);
169:
170: if (cls->methods) {
171: struct objc_method_list *catmethods;
172:
173: class_implements = cls->methods->method_count;
174: catmethods = cls->methods->method_next;
175: if (catmethods) {
176: n_categories = 0;
177: do {
178: class_implements += catmethods->method_count;
179: catmethods = catmethods->method_next;
180: if (catmethods)
181: n_categories++;
182: } while (catmethods);
183: }
184: } else {
185: class_implements = 0;
186: }
187:
188: //printf("n_categories = %d\n",n_categories);
189:
190: if (meta->methods) {
191: struct objc_method_list *catmethods;
192:
193: meta_implements = meta->methods->method_count;
194: catmethods = meta->methods->method_next;
195: if (catmethods) {
196: do {
197: meta_implements += catmethods->method_count;
198: catmethods = catmethods->method_next;
199: } while (catmethods);
200: }
201: } else {
202: meta_implements = 0;
203: }
204:
205: if (detail)
206: printf(" implements %d instance methods, %d class methods\n",
207: class_implements, meta_implements);
208:
209: n_class_implements += class_implements;
210: n_meta_implements += meta_implements;
211:
212: class_responds = _objc_class_respondsTo(cls);
213: meta_responds = _objc_class_respondsTo(meta);
214:
215: if (detail)
216: printf(" responds to %d instance methods, %d class methods\n",
217: class_responds, meta_responds);
218:
219: n_class_responds += class_responds;
220: n_meta_responds += meta_responds;
221:
222: if (cls->cache)
223: {
224: if (detail) {
225: printf(" using %u instance methods\n", cls->cache->occupied);
226: printf(" instance cache has %u slots, it is %3.2f%% full.\n",
227: cls->cache->mask+1,
228: (float)cls->cache->occupied/(cls->cache->mask+1) * 100);
229: }
230: b_class += sizeof(struct objc_cache) +
231: ((cls->cache->mask+1) * sizeof(Method));
232: n_class++;
233: }
234: if (meta->cache)
235: {
236: if (detail) {
237: printf(" using %u class methods\n", meta->cache->occupied);
238: printf(" class cache has %u slots, it is %3.2f%% full.\n",
239: meta->cache->mask+1,
240: (float)meta->cache->occupied/(meta->cache->mask+1) * 100);
241: }
242: b_meta += sizeof(struct objc_cache) +
243: ((meta->cache->mask+1) * sizeof(Method));
244: n_meta++;
245: }
246: }
247: }
248: {
249: Module *mods = objc_getModules();
250: int catcnt = 0;
251:
252: while (*mods) {
253: int i, total = (*mods)->symtab->cls_def_cnt +
254: (*mods)->symtab->cat_def_cnt;
255:
256: catcnt += (*mods)->symtab->cat_def_cnt;
257:
258: /* add categories */
259: for (i = (*mods)->symtab->cls_def_cnt; i < total; i++) {
260: //Category cat = (*mods)->symtab->defs[i];
261: //printf("Category `%s' for Class `%s'.\n", cat->category_name, cat->class_name);
262: }
263: mods++;
264: }
265: printf("\nClass Info:\n\n");
266: printf("%d classes (%d categories) - class descriptors spread across %u pages.\n",
267: n_classes, catcnt, [pagehash count]);
268: }
269: printf("%d classes currently in use\n", n_classes_used);
270: printf("%d instance methods, ",n_class_implements);
271: printf("%d instance responders\n",n_class_responds);
272: printf("%d class methods, ",n_meta_implements);
273: printf("%d class responders\n",n_meta_responds);
274:
275: if (n_class) {
276: printf("%d bytes allocated to cache instance methods ",b_class);
277: printf("(%d bytes per class)\n",
278: b_class/n_class);
279: }
280: if (n_meta) {
281: printf("%d bytes allocated to cache class methods ",b_meta);
282: printf("(%d bytes per meta class)\n",
283: b_meta/n_meta);
284: }
285:
286: {
287: Module *mods = objc_getModules();
288: int selrefs = 0;
289:
290: while (*mods) {
291: int nsels = (*mods)->symtab->sel_ref_cnt;
292: #if 0
293: int i;
294: for (i = 0; i < nsels; i++)
295: printf("refs[%d] = %s\n",i,
296: sel_getName((*mods)->symtab->refs[i]));
297: #endif
298: selrefs += nsels;
299: mods++;
300: }
301:
302: printf("\nSelector Info:\n\n");
303: printf("%d selector references\n", selrefs);
304: printf("%d unique selectors\n", (int) _sel_getMaxUid());
305: }
306: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.