[gforth] / gforth / vmgen-ex / profile.c  

gforth: gforth/vmgen-ex/profile.c


1 : anton 1.1 /* VM profiling support stuff
2 :    
3 : anton 1.8 Copyright (C) 2001,2003,2007 Free Software Foundation, Inc.
4 : anton 1.1
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 : anton 1.7 as published by the Free Software Foundation, either version 3
10 : anton 1.1 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 : anton 1.7 along with this program; if not, see http://www.gnu.org/licenses/.
19 : anton 1.1 */
20 :    
21 :     #include <stdlib.h>
22 :     #include <stdio.h>
23 :     #include <assert.h>
24 :     #include "mini.h"
25 :    
26 :     /* data structure: simple hash table with external chaining */
27 :    
28 :     #define HASH_SIZE (1<<20)
29 : anton 1.2 #define hash(p) ((((Cell)(p))/sizeof(Inst))&(HASH_SIZE-1))
30 : anton 1.1
31 : anton 1.4 #ifdef __GNUC__
32 :     typedef long long long_long;
33 :     #else
34 :     typedef long long_long;
35 :     #endif
36 :    
37 : anton 1.1 typedef struct block_count {
38 :     struct block_count *next; /* next in hash table */
39 :     struct block_count *fallthrough; /* the block that this one falls
40 :     through to without SUPER_END */
41 :     Inst *ip;
42 : anton 1.4 long_long count;
43 : anton 1.1 char **insts;
44 :     size_t ninsts;
45 :     } block_count;
46 :    
47 :     block_count *blocks[HASH_SIZE];
48 : anton 1.2 Inst *vmcode_end;
49 : anton 1.1
50 :     block_count *block_lookup(Inst *ip)
51 :     {
52 :     block_count *b = blocks[hash(ip)];
53 :    
54 :     while (b!=NULL && b->ip!=ip)
55 :     b = b->next;
56 :     return b;
57 :     }
58 :    
59 :     /* looks up present elements, inserts absent elements */
60 :     block_count *block_insert(Inst *ip)
61 :     {
62 :     block_count *b = block_lookup(ip);
63 :     block_count *new;
64 :    
65 :     if (b != NULL)
66 :     return b;
67 :     new = (block_count *)malloc(sizeof(block_count));
68 :     new->next = blocks[hash(ip)];
69 :     new->fallthrough = NULL;
70 :     new->ip = ip;
71 : anton 1.4 new->count = (long_long)0;
72 : anton 1.5 new->insts = malloc(1);
73 : anton 1.1 assert(new->insts != NULL);
74 :     new->ninsts = 0;
75 :     blocks[hash(ip)] = new;
76 :     return new;
77 :     }
78 :    
79 :     void add_inst(block_count *b, char *inst)
80 :     {
81 :     b->insts = realloc(b->insts, (b->ninsts+1) * sizeof(char *));
82 :     b->insts[b->ninsts++] = inst;
83 :     }
84 :    
85 :     void vm_count_block(Inst *ip)
86 :     {
87 :     block_insert(ip)->count++;
88 :     }
89 :    
90 :     void postprocess_block(block_count *b)
91 :     {
92 :     Inst *ip = b->ip;
93 : anton 1.2 block_count *next_block=NULL;
94 : anton 1.1
95 : anton 1.2 while (next_block == NULL && ip<vmcode_end) {
96 : anton 1.1 #include "mini-profile.i"
97 :     /* else */
98 :     {
99 :     add_inst(b,"unknown");
100 :     ip++;
101 :     }
102 :     _endif_:
103 :     next_block = block_lookup(ip);
104 : anton 1.2 }
105 : anton 1.1 /* we fell through, so set fallthrough and update the count */
106 :     b->fallthrough = next_block;
107 :     /* also update the counts of all following fallthrough blocks that
108 :     have already been processed */
109 :     while (next_block != NULL) {
110 :     next_block->count += b->count;
111 :     next_block = next_block->fallthrough;
112 :     }
113 :     }
114 :    
115 :     /* Deal with block entry by falling through from non-SUPER_END
116 :     instructions. And fill the insts and ninsts fields. */
117 :     void postprocess(void)
118 :     {
119 :     size_t i;
120 :    
121 :     for (i=0; i<HASH_SIZE; i++) {
122 :     block_count *b = blocks[i];
123 :     for (; b!=0; b = b->next)
124 :     postprocess_block(b);
125 :     }
126 :     }
127 :    
128 :     #if 0
129 :     void print_block(FILE *file, block_count *b)
130 :     {
131 :     size_t i;
132 :    
133 :     fprintf(file,"%14lld\t",b->count);
134 :     for (i=0; i<b->ninsts; i++)
135 :     fprintf(file, "%s ", b->insts[i]);
136 :     putc('\n', file);
137 :     }
138 :     #endif
139 :    
140 :     void print_block(FILE *file, block_count *b)
141 :     {
142 :     size_t i,j,k;
143 :    
144 :     for (i=2; i<12; i++)
145 :     for (j=0; i+j<=b->ninsts; j++) {
146 :     fprintf(file,"%14lld\t",b->count);
147 :     for (k=j; k<i+j; k++)
148 :     fprintf(file, "%s ", b->insts[k]);
149 :     putc('\n', file);
150 :     }
151 :     }
152 :    
153 :     void vm_print_profile(FILE *file)
154 :     {
155 :     size_t i;
156 :    
157 :     postprocess();
158 :     for (i=0; i<HASH_SIZE; i++) {
159 :     block_count *b = blocks[i];
160 :     for (; b!=0; b = b->next)
161 :     print_block(file, b);
162 :     }
163 :     }

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help