* src/vm/jit/intrp/codegen.c (codegen): Save synchronized object in
[cacao.git] / src / vm / jit / intrp / profile.c
1 /* VM profiling support stuff
2
3   Copyright (C) 2001,2003 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 "vm/jit/intrp/intrp.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 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 };
47
48 block_count *blocks[HASH_SIZE];
49
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 *vm_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   new->count = (long_long)0;
72   new->insts = malloc(1);
73   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   vm_block_insert(ip)->count++;
88 }
89
90 void vm_uncount_block(Inst *ip)
91 {
92   vm_block_insert(ip)->count--;
93 }
94
95 void postprocess_block(block_count *b)
96 {
97   Inst *ip = b->ip;
98   block_count *next_block=NULL;
99
100   if (b->count == 0)
101     return;
102   while (next_block == NULL) {
103 #include "java-profile.i"
104     /* else */
105     {
106       add_inst(b,"unknown");
107       ip++;
108     }
109   _endif_:
110     next_block = block_lookup(ip);
111   }
112   /* we fell through, so set fallthrough and update the count */
113   b->fallthrough = next_block;
114   /* also update the counts of all following fallthrough blocks that
115      have already been processed */
116   while (next_block != NULL) {
117     next_block->count += b->count;
118     next_block = next_block->fallthrough;
119   }
120 }
121
122 /* Deal with block entry by falling through from non-SUPER_END
123    instructions.  And fill the insts and ninsts fields. */
124 void postprocess(void)
125 {
126   size_t i;
127
128   for (i=0; i<HASH_SIZE; i++) {
129     block_count *b = blocks[i];
130     for (; b!=0; b = b->next)
131       postprocess_block(b);
132    }
133 }
134
135 #if 0
136 void print_block(FILE *file, block_count *b)
137 {
138   size_t i;
139
140   fprintf(file,"%14lld\t",b->count);
141   for (i=0; i<b->ninsts; i++)
142     fprintf(file, "%s ", b->insts[i]);
143   putc('\n', file);
144 }
145 #endif
146
147 void print_block(FILE *file, block_count *b)
148 {
149   size_t i,j,k;
150
151   for (i=2; i<12; i++)
152     for (j=0; i+j<=b->ninsts; j++) {
153       fprintf(file,"%14lld\t",b->count);
154       for (k=j; k<i+j; k++)
155         fprintf(file, "%s ", b->insts[k]);
156       putc('\n', file);
157     }
158 }
159
160 void vm_print_profile(FILE *file)
161 {
162   size_t i;
163
164   postprocess();
165   for (i=0; i<HASH_SIZE; i++) {
166     block_count *b = blocks[i];
167     for (; b!=0; b = b->next)
168       print_block(file, b);
169    }
170 }