tl_cache.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /***** tl_spin: tl_cache.c *****/
  10. /* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
  11. /* All Rights Reserved. This software is for educational purposes only. */
  12. /* No guarantee whatsoever is expressed or implied by the distribution of */
  13. /* this code. Permission is given to distribute this code provided that */
  14. /* this introductory message is not removed and no monies are exchanged. */
  15. /* Software written by Gerard J. Holzmann. For tool documentation see: */
  16. /* http://spinroot.com/ */
  17. /* Send all bug-reports and/or questions to: bugs@spinroot.com */
  18. /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
  19. /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
  20. #include "tl.h"
  21. typedef struct Cache {
  22. Node *before;
  23. Node *after;
  24. int same;
  25. struct Cache *nxt;
  26. } Cache;
  27. static Cache *stored = (Cache *) 0;
  28. static unsigned long Caches, CacheHits;
  29. static int ismatch(Node *, Node *);
  30. extern void fatal(char *, char *);
  31. int sameform(Node *, Node *);
  32. void
  33. ini_cache(void)
  34. {
  35. stored = (Cache *) 0;
  36. Caches = 0;
  37. CacheHits = 0;
  38. }
  39. #if 0
  40. void
  41. cache_dump(void)
  42. { Cache *d; int nr=0;
  43. printf("\nCACHE DUMP:\n");
  44. for (d = stored; d; d = d->nxt, nr++)
  45. { if (d->same) continue;
  46. printf("B%3d: ", nr); dump(d->before); printf("\n");
  47. printf("A%3d: ", nr); dump(d->after); printf("\n");
  48. }
  49. printf("============\n");
  50. }
  51. #endif
  52. Node *
  53. in_cache(Node *n)
  54. { Cache *d; int nr=0;
  55. for (d = stored; d; d = d->nxt, nr++)
  56. if (isequal(d->before, n))
  57. { CacheHits++;
  58. if (d->same && ismatch(n, d->before)) return n;
  59. return dupnode(d->after);
  60. }
  61. return ZN;
  62. }
  63. Node *
  64. cached(Node *n)
  65. { Cache *d;
  66. Node *m;
  67. if (!n) return n;
  68. if ((m = in_cache(n)) != ZN)
  69. return m;
  70. Caches++;
  71. d = (Cache *) tl_emalloc(sizeof(Cache));
  72. d->before = dupnode(n);
  73. d->after = Canonical(n); /* n is released */
  74. if (ismatch(d->before, d->after))
  75. { d->same = 1;
  76. releasenode(1, d->after);
  77. d->after = d->before;
  78. }
  79. d->nxt = stored;
  80. stored = d;
  81. return dupnode(d->after);
  82. }
  83. void
  84. cache_stats(void)
  85. {
  86. printf("cache stores : %9ld\n", Caches);
  87. printf("cache hits : %9ld\n", CacheHits);
  88. }
  89. void
  90. releasenode(int all_levels, Node *n)
  91. {
  92. if (!n) return;
  93. if (all_levels)
  94. { releasenode(1, n->lft);
  95. n->lft = ZN;
  96. releasenode(1, n->rgt);
  97. n->rgt = ZN;
  98. }
  99. tfree((void *) n);
  100. }
  101. Node *
  102. tl_nn(int t, Node *ll, Node *rl)
  103. { Node *n = (Node *) tl_emalloc(sizeof(Node));
  104. n->ntyp = (int16_t) t;
  105. n->lft = ll;
  106. n->rgt = rl;
  107. return n;
  108. }
  109. Node *
  110. getnode(Node *p)
  111. { Node *n;
  112. if (!p) return p;
  113. n = (Node *) tl_emalloc(sizeof(Node));
  114. n->ntyp = p->ntyp;
  115. n->sym = p->sym; /* same name */
  116. n->lft = p->lft;
  117. n->rgt = p->rgt;
  118. return n;
  119. }
  120. Node *
  121. dupnode(Node *n)
  122. { Node *d;
  123. if (!n) return n;
  124. d = getnode(n);
  125. d->lft = dupnode(n->lft);
  126. d->rgt = dupnode(n->rgt);
  127. return d;
  128. }
  129. int
  130. one_lft(int ntyp, Node *x, Node *in)
  131. {
  132. if (!x) return 1;
  133. if (!in) return 0;
  134. if (sameform(x, in))
  135. return 1;
  136. if (in->ntyp != ntyp)
  137. return 0;
  138. if (one_lft(ntyp, x, in->lft))
  139. return 1;
  140. return one_lft(ntyp, x, in->rgt);
  141. }
  142. int
  143. all_lfts(int ntyp, Node *from, Node *in)
  144. {
  145. if (!from) return 1;
  146. if (from->ntyp != ntyp)
  147. return one_lft(ntyp, from, in);
  148. if (!one_lft(ntyp, from->lft, in))
  149. return 0;
  150. return all_lfts(ntyp, from->rgt, in);
  151. }
  152. int
  153. sametrees(int ntyp, Node *a, Node *b)
  154. { /* toplevel is an AND or OR */
  155. /* both trees are right-linked, but the leafs */
  156. /* can be in different places in the two trees */
  157. if (!all_lfts(ntyp, a, b))
  158. return 0;
  159. return all_lfts(ntyp, b, a);
  160. }
  161. int /* a better isequal() */
  162. sameform(Node *a, Node *b)
  163. {
  164. if (!a && !b) return 1;
  165. if (!a || !b) return 0;
  166. if (a->ntyp != b->ntyp) return 0;
  167. if (a->sym
  168. && b->sym
  169. && strcmp(a->sym->name, b->sym->name) != 0)
  170. return 0;
  171. switch (a->ntyp) {
  172. case TRUE:
  173. case FALSE:
  174. return 1;
  175. case PREDICATE:
  176. if (!a->sym || !b->sym) fatal("sameform...", (char *) 0);
  177. return !strcmp(a->sym->name, b->sym->name);
  178. case NOT:
  179. #ifdef NXT
  180. case NEXT:
  181. #endif
  182. return sameform(a->lft, b->lft);
  183. case U_OPER:
  184. case V_OPER:
  185. if (!sameform(a->lft, b->lft))
  186. return 0;
  187. if (!sameform(a->rgt, b->rgt))
  188. return 0;
  189. return 1;
  190. case AND:
  191. case OR: /* the hard case */
  192. return sametrees(a->ntyp, a, b);
  193. default:
  194. printf("type: %d\n", a->ntyp);
  195. fatal("cannot happen, sameform", (char *) 0);
  196. }
  197. return 0;
  198. }
  199. int
  200. isequal(Node *a, Node *b)
  201. {
  202. if (!a && !b)
  203. return 1;
  204. if (!a || !b)
  205. { if (!a)
  206. { if (b->ntyp == TRUE)
  207. return 1;
  208. } else
  209. { if (a->ntyp == TRUE)
  210. return 1;
  211. }
  212. return 0;
  213. }
  214. if (a->ntyp != b->ntyp)
  215. return 0;
  216. if (a->sym
  217. && b->sym
  218. && strcmp(a->sym->name, b->sym->name) != 0)
  219. return 0;
  220. if (isequal(a->lft, b->lft)
  221. && isequal(a->rgt, b->rgt))
  222. return 1;
  223. return sameform(a, b);
  224. }
  225. static int
  226. ismatch(Node *a, Node *b)
  227. {
  228. if (!a && !b) return 1;
  229. if (!a || !b) return 0;
  230. if (a->ntyp != b->ntyp) return 0;
  231. if (a->sym
  232. && b->sym
  233. && strcmp(a->sym->name, b->sym->name) != 0)
  234. return 0;
  235. if (ismatch(a->lft, b->lft)
  236. && ismatch(a->rgt, b->rgt))
  237. return 1;
  238. return 0;
  239. }
  240. int
  241. any_term(Node *srch, Node *in)
  242. {
  243. if (!in) return 0;
  244. if (in->ntyp == AND)
  245. return any_term(srch, in->lft) ||
  246. any_term(srch, in->rgt);
  247. return isequal(in, srch);
  248. }
  249. int
  250. any_and(Node *srch, Node *in)
  251. {
  252. if (!in) return 0;
  253. if (srch->ntyp == AND)
  254. return any_and(srch->lft, in) &&
  255. any_and(srch->rgt, in);
  256. return any_term(srch, in);
  257. }
  258. int
  259. any_lor(Node *srch, Node *in)
  260. {
  261. if (!in) return 0;
  262. if (in->ntyp == OR)
  263. return any_lor(srch, in->lft) ||
  264. any_lor(srch, in->rgt);
  265. return isequal(in, srch);
  266. }
  267. int
  268. anywhere(int tok, Node *srch, Node *in)
  269. {
  270. if (!in) return 0;
  271. switch (tok) {
  272. case AND: return any_and(srch, in);
  273. case OR: return any_lor(srch, in);
  274. case 0: return any_term(srch, in);
  275. }
  276. fatal("cannot happen, anywhere", (char *) 0);
  277. return 0;
  278. }