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