Annotation of gforth/vmgen-ex/profile.c, revision 1.7

1.1       anton       1: /* VM profiling support stuff
                      2: 
1.6       anton       3:   Copyright (C) 2001,2003 Free Software Foundation, Inc.
1.1       anton       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
1.7     ! anton       9:   as published by the Free Software Foundation, either version 3
1.1       anton      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
1.7     ! anton      18:   along with this program; if not, see http://www.gnu.org/licenses/.
1.1       anton      19: */
                     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)
1.2       anton      29: #define hash(p) ((((Cell)(p))/sizeof(Inst))&(HASH_SIZE-1))
1.1       anton      30: 
1.4       anton      31: #ifdef __GNUC__
                     32: typedef long long long_long;
                     33: #else
                     34: typedef long long_long;
                     35: #endif
                     36: 
1.1       anton      37: 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;
1.4       anton      42:   long_long count;
1.1       anton      43:   char **insts;
                     44:   size_t ninsts;
                     45: } block_count;
                     46: 
                     47: block_count *blocks[HASH_SIZE];
1.2       anton      48: Inst *vmcode_end;
1.1       anton      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 *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;
1.4       anton      71:   new->count = (long_long)0;
1.5       anton      72:   new->insts = malloc(1);
1.1       anton      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:   block_insert(ip)->count++;
                     88: }
                     89: 
                     90: void postprocess_block(block_count *b)
                     91: {
                     92:   Inst *ip = b->ip;
1.2       anton      93:   block_count *next_block=NULL;
1.1       anton      94: 
1.2       anton      95:   while (next_block == NULL && ip<vmcode_end) {
1.1       anton      96: #include "mini-profile.i"
                     97:     /* else */
                     98:     {
                     99:       add_inst(b,"unknown");
                    100:       ip++;
                    101:     }
                    102:   _endif_:
                    103:     next_block = block_lookup(ip);
1.2       anton     104:   }
1.1       anton     105:   /* 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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>