Annotation of gforth/engine/profile.c, revision 1.8

1.1       anton       1: /* VM profiling support stuff
                      2: 
1.8     ! anton       3:   Copyright (C) 2001,2002 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
                      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>