File:  [gforth] / gforth / vmgen-ex / profile.c
Revision 1.4: download - view: text, annotated - select for diffs
Sun Jun 2 17:02:56 2002 UTC (17 years, 6 months ago) by anton
Branches: MAIN
CVS tags: HEAD
vmgen* now works with lcc and "gcc -O3 -ansi --pedantic -U__GNUC__"

    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 <stdlib.h>
   23: #include <stdio.h>
   24: #include <assert.h>
   25: #include "mini.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: typedef 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: } block_count;
   47: 
   48: block_count *blocks[HASH_SIZE];
   49: Inst *vmcode_end;
   50: 
   51: block_count *block_lookup(Inst *ip)
   52: {
   53:   block_count *b = blocks[hash(ip)];
   54: 
   55:   while (b!=NULL && b->ip!=ip)
   56:     b = b->next;
   57:   return b;
   58: }
   59: 
   60: /* looks up present elements, inserts absent elements */
   61: block_count *block_insert(Inst *ip)
   62: { 
   63:   block_count *b = block_lookup(ip);
   64:   block_count *new;
   65: 
   66:   if (b != NULL)
   67:     return b;
   68:   new = (block_count *)malloc(sizeof(block_count));
   69:   new->next = blocks[hash(ip)];
   70:   new->fallthrough = NULL;
   71:   new->ip = ip;
   72:   new->count = (long_long)0;
   73:   new->insts = malloc(0);
   74:   assert(new->insts != NULL);
   75:   new->ninsts = 0;
   76:   blocks[hash(ip)] = new;
   77:   return new;
   78: }
   79: 
   80: void add_inst(block_count *b, char *inst)
   81: {
   82:   b->insts = realloc(b->insts, (b->ninsts+1) * sizeof(char *));
   83:   b->insts[b->ninsts++] = inst;
   84: }
   85: 
   86: void vm_count_block(Inst *ip)
   87: {
   88:   block_insert(ip)->count++;
   89: }
   90: 
   91: void postprocess_block(block_count *b)
   92: {
   93:   Inst *ip = b->ip;
   94:   block_count *next_block=NULL;
   95: 
   96:   while (next_block == NULL && ip<vmcode_end) {
   97: #include "mini-profile.i"
   98:     /* else */
   99:     {
  100:       add_inst(b,"unknown");
  101:       ip++;
  102:     }
  103:   _endif_:
  104:     next_block = block_lookup(ip);
  105:   }
  106:   /* we fell through, so set fallthrough and update the count */
  107:   b->fallthrough = next_block;
  108:   /* also update the counts of all following fallthrough blocks that
  109:      have already been processed */
  110:   while (next_block != NULL) {
  111:     next_block->count += b->count;
  112:     next_block = next_block->fallthrough;
  113:   }
  114: }
  115: 
  116: /* Deal with block entry by falling through from non-SUPER_END
  117:    instructions.  And fill the insts and ninsts fields. */
  118: void postprocess(void)
  119: {
  120:   size_t i;
  121: 
  122:   for (i=0; i<HASH_SIZE; i++) {
  123:     block_count *b = blocks[i];
  124:     for (; b!=0; b = b->next)
  125:       postprocess_block(b);
  126:    }
  127: }
  128: 
  129: #if 0
  130: void print_block(FILE *file, block_count *b)
  131: {
  132:   size_t i;
  133: 
  134:   fprintf(file,"%14lld\t",b->count);
  135:   for (i=0; i<b->ninsts; i++)
  136:     fprintf(file, "%s ", b->insts[i]);
  137:   putc('\n', file);
  138: }
  139: #endif
  140: 
  141: void print_block(FILE *file, block_count *b)
  142: {
  143:   size_t i,j,k;
  144: 
  145:   for (i=2; i<12; i++)
  146:     for (j=0; i+j<=b->ninsts; j++) {
  147:       fprintf(file,"%14lld\t",b->count);
  148:       for (k=j; k<i+j; k++)
  149: 	fprintf(file, "%s ", b->insts[k]);
  150:       putc('\n', file);
  151:     }
  152: }
  153: 
  154: void vm_print_profile(FILE *file)
  155: {
  156:   size_t i;
  157: 
  158:   postprocess();
  159:   for (i=0; i<HASH_SIZE; i++) {
  160:     block_count *b = blocks[i];
  161:     for (; b!=0; b = b->next)
  162:       print_block(file, b);
  163:    }
  164: }

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