123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- /***** tl_spin: tl_cache.c *****/
- /* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
- /* All Rights Reserved. This software is for educational purposes only. */
- /* No guarantee whatsoever is expressed or implied by the distribution of */
- /* this code. Permission is given to distribute this code provided that */
- /* this introductory message is not removed and no monies are exchanged. */
- /* Software written by Gerard J. Holzmann. For tool documentation see: */
- /* http://spinroot.com/ */
- /* Send all bug-reports and/or questions to: bugs@spinroot.com */
- /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
- /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
- #include "tl.h"
- typedef struct Cache {
- Node *before;
- Node *after;
- int same;
- struct Cache *nxt;
- } Cache;
- static Cache *stored = (Cache *) 0;
- static unsigned long Caches, CacheHits;
- static int ismatch(Node *, Node *);
- extern void fatal(char *, char *);
- int sameform(Node *, Node *);
- void
- ini_cache(void)
- {
- stored = (Cache *) 0;
- Caches = 0;
- CacheHits = 0;
- }
- #if 0
- void
- cache_dump(void)
- { Cache *d; int nr=0;
- printf("\nCACHE DUMP:\n");
- for (d = stored; d; d = d->nxt, nr++)
- { if (d->same) continue;
- printf("B%3d: ", nr); dump(d->before); printf("\n");
- printf("A%3d: ", nr); dump(d->after); printf("\n");
- }
- printf("============\n");
- }
- #endif
- Node *
- in_cache(Node *n)
- { Cache *d; int nr=0;
- for (d = stored; d; d = d->nxt, nr++)
- if (isequal(d->before, n))
- { CacheHits++;
- if (d->same && ismatch(n, d->before)) return n;
- return dupnode(d->after);
- }
- return ZN;
- }
- Node *
- cached(Node *n)
- { Cache *d;
- Node *m;
- if (!n) return n;
- if ((m = in_cache(n)) != ZN)
- return m;
- Caches++;
- d = (Cache *) tl_emalloc(sizeof(Cache));
- d->before = dupnode(n);
- d->after = Canonical(n); /* n is released */
- if (ismatch(d->before, d->after))
- { d->same = 1;
- releasenode(1, d->after);
- d->after = d->before;
- }
- d->nxt = stored;
- stored = d;
- return dupnode(d->after);
- }
- void
- cache_stats(void)
- {
- printf("cache stores : %9ld\n", Caches);
- printf("cache hits : %9ld\n", CacheHits);
- }
- void
- releasenode(int all_levels, Node *n)
- {
- if (!n) return;
- if (all_levels)
- { releasenode(1, n->lft);
- n->lft = ZN;
- releasenode(1, n->rgt);
- n->rgt = ZN;
- }
- tfree((void *) n);
- }
- Node *
- tl_nn(int t, Node *ll, Node *rl)
- { Node *n = (Node *) tl_emalloc(sizeof(Node));
- n->ntyp = (int16_t) t;
- n->lft = ll;
- n->rgt = rl;
- return n;
- }
- Node *
- getnode(Node *p)
- { Node *n;
- if (!p) return p;
- n = (Node *) tl_emalloc(sizeof(Node));
- n->ntyp = p->ntyp;
- n->sym = p->sym; /* same name */
- n->lft = p->lft;
- n->rgt = p->rgt;
- return n;
- }
- Node *
- dupnode(Node *n)
- { Node *d;
- if (!n) return n;
- d = getnode(n);
- d->lft = dupnode(n->lft);
- d->rgt = dupnode(n->rgt);
- return d;
- }
- int
- one_lft(int ntyp, Node *x, Node *in)
- {
- if (!x) return 1;
- if (!in) return 0;
- if (sameform(x, in))
- return 1;
- if (in->ntyp != ntyp)
- return 0;
- if (one_lft(ntyp, x, in->lft))
- return 1;
- return one_lft(ntyp, x, in->rgt);
- }
- int
- all_lfts(int ntyp, Node *from, Node *in)
- {
- if (!from) return 1;
- if (from->ntyp != ntyp)
- return one_lft(ntyp, from, in);
- if (!one_lft(ntyp, from->lft, in))
- return 0;
- return all_lfts(ntyp, from->rgt, in);
- }
- int
- sametrees(int ntyp, Node *a, Node *b)
- { /* toplevel is an AND or OR */
- /* both trees are right-linked, but the leafs */
- /* can be in different places in the two trees */
- if (!all_lfts(ntyp, a, b))
- return 0;
- return all_lfts(ntyp, b, a);
- }
- int /* a better isequal() */
- sameform(Node *a, Node *b)
- {
- if (!a && !b) return 1;
- if (!a || !b) return 0;
- if (a->ntyp != b->ntyp) return 0;
- if (a->sym
- && b->sym
- && strcmp(a->sym->name, b->sym->name) != 0)
- return 0;
- switch (a->ntyp) {
- case TRUE:
- case FALSE:
- return 1;
- case PREDICATE:
- if (!a->sym || !b->sym) fatal("sameform...", (char *) 0);
- return !strcmp(a->sym->name, b->sym->name);
- case NOT:
- #ifdef NXT
- case NEXT:
- #endif
- return sameform(a->lft, b->lft);
- case U_OPER:
- case V_OPER:
- if (!sameform(a->lft, b->lft))
- return 0;
- if (!sameform(a->rgt, b->rgt))
- return 0;
- return 1;
- case AND:
- case OR: /* the hard case */
- return sametrees(a->ntyp, a, b);
- default:
- printf("type: %d\n", a->ntyp);
- fatal("cannot happen, sameform", (char *) 0);
- }
- return 0;
- }
- int
- isequal(Node *a, Node *b)
- {
- if (!a && !b)
- return 1;
- if (!a || !b)
- { if (!a)
- { if (b->ntyp == TRUE)
- return 1;
- } else
- { if (a->ntyp == TRUE)
- return 1;
- }
- return 0;
- }
- if (a->ntyp != b->ntyp)
- return 0;
- if (a->sym
- && b->sym
- && strcmp(a->sym->name, b->sym->name) != 0)
- return 0;
- if (isequal(a->lft, b->lft)
- && isequal(a->rgt, b->rgt))
- return 1;
- return sameform(a, b);
- }
- static int
- ismatch(Node *a, Node *b)
- {
- if (!a && !b) return 1;
- if (!a || !b) return 0;
- if (a->ntyp != b->ntyp) return 0;
- if (a->sym
- && b->sym
- && strcmp(a->sym->name, b->sym->name) != 0)
- return 0;
- if (ismatch(a->lft, b->lft)
- && ismatch(a->rgt, b->rgt))
- return 1;
- return 0;
- }
- int
- any_term(Node *srch, Node *in)
- {
- if (!in) return 0;
- if (in->ntyp == AND)
- return any_term(srch, in->lft) ||
- any_term(srch, in->rgt);
- return isequal(in, srch);
- }
- int
- any_and(Node *srch, Node *in)
- {
- if (!in) return 0;
- if (srch->ntyp == AND)
- return any_and(srch->lft, in) &&
- any_and(srch->rgt, in);
- return any_term(srch, in);
- }
- int
- any_lor(Node *srch, Node *in)
- {
- if (!in) return 0;
- if (in->ntyp == OR)
- return any_lor(srch, in->lft) ||
- any_lor(srch, in->rgt);
- return isequal(in, srch);
- }
- int
- anywhere(int tok, Node *srch, Node *in)
- {
- if (!in) return 0;
- switch (tok) {
- case AND: return any_and(srch, in);
- case OR: return any_lor(srch, in);
- case 0: return any_term(srch, in);
- }
- fatal("cannot happen, anywhere", (char *) 0);
- return 0;
- }
|