1: /* VM profiling support stuff
2:
3: Copyright (C) 2001 Free Software Foundation, Inc.
4:
5: This file is part of Gforth.
6:
7: Gforth is free software; you can redistribute it and/or
8: modify it under the terms of the GNU General Public License
9: as published by the Free Software Foundation; either version 2
10: of the License, or (at your option) any later version.
11:
12: This program is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with this program; if not, write to the Free Software
19: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20: */
21:
22: #include <stdlib.h>
23: #include <stdio.h>
24: #include <assert.h>
25: #include "mini.h"
26:
27: /* data structure: simple hash table with external chaining */
28:
29: #define HASH_SIZE (1<<20)
30: #define hash(p) ((((Cell)(p))/sizeof(Inst))&(HASH_SIZE-1))
31:
32: #ifdef __GNUC__
33: typedef long long long_long;
34: #else
35: typedef long long_long;
36: #endif
37:
38: typedef struct block_count {
39: struct block_count *next; /* next in hash table */
40: struct block_count *fallthrough; /* the block that this one falls
41: through to without SUPER_END */
42: Inst *ip;
43: long_long count;
44: char **insts;
45: size_t ninsts;
46: } block_count;
47:
48: block_count *blocks[HASH_SIZE];
49: Inst *vmcode_end;
50:
51: block_count *block_lookup(Inst *ip)
52: {
53: block_count *b = blocks[hash(ip)];
54:
55: while (b!=NULL && b->ip!=ip)
56: b = b->next;
57: return b;
58: }
59:
60: /* looks up present elements, inserts absent elements */
61: block_count *block_insert(Inst *ip)
62: {
63: block_count *b = block_lookup(ip);
64: block_count *new;
65:
66: if (b != NULL)
67: return b;
68: new = (block_count *)malloc(sizeof(block_count));
69: new->next = blocks[hash(ip)];
70: new->fallthrough = NULL;
71: new->ip = ip;
72: new->count = (long_long)0;
73: new->insts = malloc(1);
74: assert(new->insts != NULL);
75: new->ninsts = 0;
76: blocks[hash(ip)] = new;
77: return new;
78: }
79:
80: void add_inst(block_count *b, char *inst)
81: {
82: b->insts = realloc(b->insts, (b->ninsts+1) * sizeof(char *));
83: b->insts[b->ninsts++] = inst;
84: }
85:
86: void vm_count_block(Inst *ip)
87: {
88: block_insert(ip)->count++;
89: }
90:
91: void postprocess_block(block_count *b)
92: {
93: Inst *ip = b->ip;
94: block_count *next_block=NULL;
95:
96: while (next_block == NULL && ip<vmcode_end) {
97: #include "mini-profile.i"
98: /* else */
99: {
100: add_inst(b,"unknown");
101: ip++;
102: }
103: _endif_:
104: next_block = block_lookup(ip);
105: }
106: /* we fell through, so set fallthrough and update the count */
107: b->fallthrough = next_block;
108: /* also update the counts of all following fallthrough blocks that
109: have already been processed */
110: while (next_block != NULL) {
111: next_block->count += b->count;
112: next_block = next_block->fallthrough;
113: }
114: }
115:
116: /* Deal with block entry by falling through from non-SUPER_END
117: instructions. And fill the insts and ninsts fields. */
118: void postprocess(void)
119: {
120: size_t i;
121:
122: for (i=0; i<HASH_SIZE; i++) {
123: block_count *b = blocks[i];
124: for (; b!=0; b = b->next)
125: postprocess_block(b);
126: }
127: }
128:
129: #if 0
130: void print_block(FILE *file, block_count *b)
131: {
132: size_t i;
133:
134: fprintf(file,"%14lld\t",b->count);
135: for (i=0; i<b->ninsts; i++)
136: fprintf(file, "%s ", b->insts[i]);
137: putc('\n', file);
138: }
139: #endif
140:
141: void print_block(FILE *file, block_count *b)
142: {
143: size_t i,j,k;
144:
145: for (i=2; i<12; i++)
146: for (j=0; i+j<=b->ninsts; j++) {
147: fprintf(file,"%14lld\t",b->count);
148: for (k=j; k<i+j; k++)
149: fprintf(file, "%s ", b->insts[k]);
150: putc('\n', file);
151: }
152: }
153:
154: void vm_print_profile(FILE *file)
155: {
156: size_t i;
157:
158: postprocess();
159: for (i=0; i<HASH_SIZE; i++) {
160: block_count *b = blocks[i];
161: for (; b!=0; b = b->next)
162: print_block(file, b);
163: }
164: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>