Annotation of gforth/vmgen-ex/profile.c, revision 1.3
1.1 anton 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)
1.2 anton 30: #define hash(p) ((((Cell)(p))/sizeof(Inst))&(HASH_SIZE-1))
1.1 anton 31:
32: typedef struct block_count {
33: struct block_count *next; /* next in hash table */
34: struct block_count *fallthrough; /* the block that this one falls
35: through to without SUPER_END */
36: Inst *ip;
37: long long count;
38: char **insts;
39: size_t ninsts;
40: } block_count;
41:
42: block_count *blocks[HASH_SIZE];
1.2 anton 43: Inst *vmcode_end;
1.1 anton 44:
45: block_count *block_lookup(Inst *ip)
46: {
47: block_count *b = blocks[hash(ip)];
48:
49: while (b!=NULL && b->ip!=ip)
50: b = b->next;
51: return b;
52: }
53:
54: /* looks up present elements, inserts absent elements */
55: block_count *block_insert(Inst *ip)
56: {
57: block_count *b = block_lookup(ip);
58: block_count *new;
59:
60: if (b != NULL)
61: return b;
62: new = (block_count *)malloc(sizeof(block_count));
63: new->next = blocks[hash(ip)];
64: new->fallthrough = NULL;
65: new->ip = ip;
66: new->count = 0LL;
67: new->insts = malloc(0);
68: assert(new->insts != NULL);
69: new->ninsts = 0;
70: blocks[hash(ip)] = new;
71: return new;
72: }
73:
74: void add_inst(block_count *b, char *inst)
75: {
76: b->insts = realloc(b->insts, (b->ninsts+1) * sizeof(char *));
77: b->insts[b->ninsts++] = inst;
78: }
79:
80: void vm_count_block(Inst *ip)
81: {
82: block_insert(ip)->count++;
83: }
84:
85: void postprocess_block(block_count *b)
86: {
87: Inst *ip = b->ip;
1.2 anton 88: block_count *next_block=NULL;
1.1 anton 89:
1.2 anton 90: while (next_block == NULL && ip<vmcode_end) {
1.1 anton 91: #include "mini-profile.i"
92: /* else */
93: {
94: add_inst(b,"unknown");
95: ip++;
96: }
97: _endif_:
98: next_block = block_lookup(ip);
1.2 anton 99: }
1.1 anton 100: /* we fell through, so set fallthrough and update the count */
101: b->fallthrough = next_block;
102: /* also update the counts of all following fallthrough blocks that
103: have already been processed */
104: while (next_block != NULL) {
105: next_block->count += b->count;
106: next_block = next_block->fallthrough;
107: }
108: }
109:
110: /* Deal with block entry by falling through from non-SUPER_END
111: instructions. And fill the insts and ninsts fields. */
112: void postprocess(void)
113: {
114: size_t i;
115:
116: for (i=0; i<HASH_SIZE; i++) {
117: block_count *b = blocks[i];
118: for (; b!=0; b = b->next)
119: postprocess_block(b);
120: }
121: }
122:
123: #if 0
124: void print_block(FILE *file, block_count *b)
125: {
126: size_t i;
127:
128: fprintf(file,"%14lld\t",b->count);
129: for (i=0; i<b->ninsts; i++)
130: fprintf(file, "%s ", b->insts[i]);
131: putc('\n', file);
132: }
133: #endif
134:
135: void print_block(FILE *file, block_count *b)
136: {
137: size_t i,j,k;
138:
139: for (i=2; i<12; i++)
140: for (j=0; i+j<=b->ninsts; j++) {
141: fprintf(file,"%14lld\t",b->count);
142: for (k=j; k<i+j; k++)
143: fprintf(file, "%s ", b->insts[k]);
144: putc('\n', file);
145: }
146: }
147:
148: void vm_print_profile(FILE *file)
149: {
150: size_t i;
151:
152: postprocess();
153: for (i=0; i<HASH_SIZE; i++) {
154: block_count *b = blocks[i];
155: for (; b!=0; b = b->next)
156: print_block(file, b);
157: }
158: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>