Annotation of gforth/engine/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 "config.h"
! 23: #include <stdlib.h>
! 24: #include <stdio.h>
! 25: #include "forth.h"
! 26:
! 27: /* data structure: simple hash table with external chaining */
! 28:
! 29: #define HASH_SIZE (1<<20)
! 30:
! 31: typedef struct block_count {
! 32: struct block_count *next; /* next in hash table */
! 33: struct block_count *fallthrough; /* the block that this one falls
! 34: through to without SUPER_END */
! 35: Xt *ip;
! 36: long long count;
! 37: char **insts;
! 38: size_t ninsts;
! 39: } block_count;
! 40:
! 41: block_count *blocks[HASH_SIZE];
! 42:
! 43: #define hash(p) ((((Cell)(p))/sizeof(Xt))&(HASH_SIZE-1))
! 44:
! 45: block_count *block_lookup(Xt *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(Xt *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: new->ninsts = 0;
! 69: blocks[hash(ip)] = new;
! 70: return new;
! 71: }
! 72:
! 73: void add_inst(block_count *b, char *inst)
! 74: {
! 75: b->insts = realloc(b->insts, b->ninsts * sizeof(char *));
! 76: b->insts[b->ninsts++] = inst;
! 77: }
! 78:
! 79: void vm_count_block(Xt *ip)
! 80: {
! 81: block_insert(ip)->count++;
! 82: }
! 83:
! 84: /* !! fix this */
! 85: #define VM_INST(n) NULL
! 86:
! 87: void postprocess_block(block_count *b)
! 88: {
! 89: Xt *ip = b->ip;
! 90: block_count *next_block;
! 91:
! 92: do {
! 93: #include "profile.i"
! 94: /* else */
! 95: {
! 96: add_inst(b,"unknown");
! 97: ip++;
! 98: }
! 99: next_block = block_lookup(ip);
! 100: } while (next_block == NULL);
! 101: /* we fell through, so set fallthrough and update the count */
! 102: b->fallthrough = next_block;
! 103: /* also update the counts of all following fallthrough blocks that
! 104: have already been processed */
! 105: while (next_block != NULL) {
! 106: next_block->count += b->count;
! 107: next_block = next_block->fallthrough;
! 108: }
! 109: }
! 110:
! 111: /* Deal with block entry by falling through from non-SUPER_END
! 112: instructions. And fill the insts and ninsts fields. */
! 113: void postprocess(void)
! 114: {
! 115: size_t i;
! 116:
! 117: for (i=0; i<HASH_SIZE; i++) {
! 118: block_count *b = blocks[i];
! 119: for (; b!=0; b = b->next)
! 120: postprocess_block(b);
! 121: }
! 122: }
! 123:
! 124: void print_block(FILE *file, block_count *b)
! 125: {
! 126: fprintf(file,"%12lld ip=%p\n",b->count,b->ip);
! 127: }
! 128:
! 129: void vm_print_profile(FILE *file)
! 130: {
! 131: size_t i;
! 132:
! 133: postprocess();
! 134: for (i=0; i<HASH_SIZE; i++) {
! 135: block_count *b = blocks[i];
! 136: for (; b!=0; b = b->next)
! 137: print_block(file, b);
! 138: }
! 139: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>