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