heap.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. #include "lib9.h"
  2. #include "isa.h"
  3. #include "interp.h"
  4. #include "pool.h"
  5. #include "raise.h"
  6. void freearray(Heap*, int);
  7. void freelist(Heap*, int);
  8. void freemodlink(Heap*, int);
  9. void freechan(Heap*, int);
  10. Type Tarray = { 1, freearray, markarray, sizeof(Array) };
  11. Type Tstring = { 1, freestring, noptrs, sizeof(String) };
  12. Type Tlist = { 1, freelist, marklist, sizeof(List) };
  13. Type Tmodlink = { 1, freemodlink, markheap, -1, 1, 0, 0, { 0x80 } };
  14. Type Tchannel = { 1, freechan, markheap, sizeof(Channel), 1,0,0,{0x80} };
  15. Type Tptr = { 1, 0, markheap, sizeof(WORD*), 1, 0, 0, { 0x80 } };
  16. Type Tbyte = { 1, 0, 0, 1 };
  17. Type Tword = { 1, 0, 0, sizeof(WORD) };
  18. Type Tlong = { 1, 0, 0, sizeof(LONG) };
  19. Type Treal = { 1, 0, 0, sizeof(REAL) };
  20. extern Pool* heapmem;
  21. extern int mutator;
  22. void (*heapmonitor)(int, void*, ulong);
  23. #define BIT(bt, nb) (bt & (1<<nb))
  24. void
  25. freeptrs(void *v, Type *t)
  26. {
  27. int c;
  28. WORD **w, *x;
  29. uchar *p, *ep;
  30. if(t->np == 0)
  31. return;
  32. w = (WORD**)v;
  33. p = t->map;
  34. ep = p + t->np;
  35. while(p < ep) {
  36. c = *p;
  37. if(c != 0) {
  38. if(BIT(c, 0) && (x = w[7]) != H) destroy(x);
  39. if(BIT(c, 1) && (x = w[6]) != H) destroy(x);
  40. if(BIT(c, 2) && (x = w[5]) != H) destroy(x);
  41. if(BIT(c, 3) && (x = w[4]) != H) destroy(x);
  42. if(BIT(c, 4) && (x = w[3]) != H) destroy(x);
  43. if(BIT(c, 5) && (x = w[2]) != H) destroy(x);
  44. if(BIT(c, 6) && (x = w[1]) != H) destroy(x);
  45. if(BIT(c, 7) && (x = w[0]) != H) destroy(x);
  46. }
  47. p++;
  48. w += 8;
  49. }
  50. }
  51. /*
  52. void
  53. nilptrs(void *v, Type *t)
  54. {
  55. int c, i;
  56. WORD **w;
  57. uchar *p, *ep;
  58. w = (WORD**)v;
  59. p = t->map;
  60. ep = p + t->np;
  61. while(p < ep) {
  62. c = *p;
  63. for(i = 0; i < 8; i++){
  64. if(BIT(c, 7)) *w = H;
  65. c <<= 1;
  66. w++;
  67. }
  68. p++;
  69. }
  70. }
  71. */
  72. void
  73. freechan(Heap *h, int swept)
  74. {
  75. Channel *c;
  76. USED(swept);
  77. c = H2D(Channel*, h);
  78. if(c->mover == movtmp)
  79. freetype(c->mid.t);
  80. killcomm(&c->send);
  81. killcomm(&c->recv);
  82. if (!swept && c->buf != H)
  83. destroy(c->buf);
  84. }
  85. void
  86. freestring(Heap *h, int swept)
  87. {
  88. String *s;
  89. USED(swept);
  90. s = H2D(String*, h);
  91. if(s->tmp != nil)
  92. free(s->tmp);
  93. }
  94. void
  95. freearray(Heap *h, int swept)
  96. {
  97. int i;
  98. Type *t;
  99. uchar *v;
  100. Array *a;
  101. a = H2D(Array*, h);
  102. t = a->t;
  103. if(!swept) {
  104. if(a->root != H)
  105. destroy(a->root);
  106. else
  107. if(t->np != 0) {
  108. v = a->data;
  109. for(i = 0; i < a->len; i++) {
  110. freeptrs(v, t);
  111. v += t->size;
  112. }
  113. }
  114. }
  115. if(t->ref-- == 1) {
  116. free(t->initialize);
  117. free(t);
  118. }
  119. }
  120. void
  121. freelist(Heap *h, int swept)
  122. {
  123. Type *t;
  124. List *l;
  125. Heap *th;
  126. l = H2D(List*, h);
  127. t = l->t;
  128. if(t != nil) {
  129. if(!swept && t->np)
  130. freeptrs(l->data, t);
  131. t->ref--;
  132. if(t->ref == 0) {
  133. free(t->initialize);
  134. free(t);
  135. }
  136. }
  137. if(swept)
  138. return;
  139. l = l->tail;
  140. while(l != (List*)H) {
  141. t = l->t;
  142. th = D2H(l);
  143. if(th->ref-- != 1)
  144. break;
  145. th->t->ref--; /* should be &Tlist and ref shouldn't go to 0 here nor be 0 already */
  146. if(t != nil) {
  147. if (t->np)
  148. freeptrs(l->data, t);
  149. t->ref--;
  150. if(t->ref == 0) {
  151. free(t->initialize);
  152. free(t);
  153. }
  154. }
  155. l = l->tail;
  156. if(heapmonitor != nil)
  157. heapmonitor(1, th, 0);
  158. poolfree(heapmem, th);
  159. }
  160. }
  161. void
  162. freemodlink(Heap *h, int swept)
  163. {
  164. Modlink *ml;
  165. ml = H2D(Modlink*, h);
  166. if(ml->m->rt == DYNMOD)
  167. freedyndata(ml);
  168. else if(!swept)
  169. destroy(ml->MP);
  170. unload(ml->m);
  171. }
  172. int
  173. heapref(void *v)
  174. {
  175. return D2H(v)->ref;
  176. }
  177. void
  178. freeheap(Heap *h, int swept)
  179. {
  180. Type *t;
  181. if(swept)
  182. return;
  183. t = h->t;
  184. if (t->np)
  185. freeptrs(H2D(void*, h), t);
  186. }
  187. void
  188. destroy(void *v)
  189. {
  190. Heap *h;
  191. Type *t;
  192. if(v == H)
  193. return;
  194. h = D2H(v);
  195. { Bhdr *b; D2B(b, h); } /* consistency check */
  196. if(--h->ref > 0 || gchalt > 64) /* Protect 'C' thread stack */
  197. return;
  198. if(heapmonitor != nil)
  199. heapmonitor(1, h, 0);
  200. t = h->t;
  201. if(t != nil) {
  202. gclock();
  203. t->free(h, 0);
  204. gcunlock();
  205. freetype(t);
  206. }
  207. poolfree(heapmem, h);
  208. }
  209. Type*
  210. dtype(void (*destroy)(Heap*, int), int size, uchar *map, int mapsize)
  211. {
  212. Type *t;
  213. t = malloc(sizeof(Type)-sizeof(t->map)+mapsize);
  214. if(t != nil) {
  215. t->ref = 1;
  216. t->free = destroy;
  217. t->mark = markheap;
  218. t->size = size;
  219. t->np = mapsize;
  220. memmove(t->map, map, mapsize);
  221. }
  222. return t;
  223. }
  224. void*
  225. checktype(void *v, Type *t, char *name, int newref)
  226. {
  227. Heap *h;
  228. if(v == H || v == nil)
  229. error(exNilref);
  230. h = D2H(v);
  231. if(t == nil || h->t != t)
  232. errorf("%s: %s", exType, name);
  233. if(newref){
  234. h->ref++;
  235. Setmark(h);
  236. }
  237. return v;
  238. }
  239. void
  240. freetype(Type *t)
  241. {
  242. if(t == nil || --t->ref > 0)
  243. return;
  244. free(t->initialize);
  245. free(t);
  246. }
  247. void
  248. incmem(void *vw, Type *t)
  249. {
  250. Heap *h;
  251. uchar *p;
  252. int i, c, m;
  253. WORD **w, **q, *wp;
  254. w = (WORD**)vw;
  255. p = t->map;
  256. for(i = 0; i < t->np; i++) {
  257. c = *p++;
  258. if(c != 0) {
  259. q = w;
  260. for(m = 0x80; m != 0; m >>= 1) {
  261. if((c & m) && (wp = *q) != H) {
  262. h = D2H(wp);
  263. h->ref++;
  264. Setmark(h);
  265. }
  266. q++;
  267. }
  268. }
  269. w += 8;
  270. }
  271. }
  272. void
  273. scanptrs(void *vw, Type *t, void (*f)(void*))
  274. {
  275. uchar *p;
  276. int i, c, m;
  277. WORD **w, **q, *wp;
  278. w = (WORD**)vw;
  279. p = t->map;
  280. for(i = 0; i < t->np; i++) {
  281. c = *p++;
  282. if(c != 0) {
  283. q = w;
  284. for(m = 0x80; m != 0; m >>= 1) {
  285. if((c & m) && (wp = *q) != H)
  286. f(D2H(wp));
  287. q++;
  288. }
  289. }
  290. w += 8;
  291. }
  292. }
  293. void
  294. initmem(Type *t, void *vw)
  295. {
  296. int c;
  297. WORD **w;
  298. uchar *p, *ep;
  299. w = (WORD**)vw;
  300. p = t->map;
  301. ep = p + t->np;
  302. while(p < ep) {
  303. c = *p;
  304. if(c != 0) {
  305. if(BIT(c, 0)) w[7] = H;
  306. if(BIT(c, 1)) w[6] = H;
  307. if(BIT(c, 2)) w[5] = H;
  308. if(BIT(c, 3)) w[4] = H;
  309. if(BIT(c, 4)) w[3] = H;
  310. if(BIT(c, 5)) w[2] = H;
  311. if(BIT(c, 6)) w[1] = H;
  312. if(BIT(c, 7)) w[0] = H;
  313. }
  314. p++;
  315. w += 8;
  316. }
  317. }
  318. Heap*
  319. nheap(int n)
  320. {
  321. Heap *h;
  322. h = poolalloc(heapmem, sizeof(Heap)+n);
  323. if(h == nil)
  324. error(exHeap);
  325. h->t = nil;
  326. h->ref = 1;
  327. h->color = mutator;
  328. if(heapmonitor != nil)
  329. heapmonitor(0, h, n);
  330. return h;
  331. }
  332. Heap*
  333. heapz(Type *t)
  334. {
  335. Heap *h;
  336. h = poolalloc(heapmem, sizeof(Heap)+t->size);
  337. if(h == nil)
  338. error(exHeap);
  339. h->t = t;
  340. t->ref++;
  341. h->ref = 1;
  342. h->color = mutator;
  343. memset(H2D(void*, h), 0, t->size);
  344. if(t->np)
  345. initmem(t, H2D(void*, h));
  346. if(heapmonitor != nil)
  347. heapmonitor(0, h, t->size);
  348. return h;
  349. }
  350. Heap*
  351. heap(Type *t)
  352. {
  353. Heap *h;
  354. h = poolalloc(heapmem, sizeof(Heap)+t->size);
  355. if(h == nil)
  356. error(exHeap);
  357. h->t = t;
  358. t->ref++;
  359. h->ref = 1;
  360. h->color = mutator;
  361. if(t->np)
  362. initmem(t, H2D(void*, h));
  363. if(heapmonitor != nil)
  364. heapmonitor(0, h, t->size);
  365. return h;
  366. }
  367. Heap*
  368. heaparray(Type *t, int sz)
  369. {
  370. Heap *h;
  371. Array *a;
  372. h = nheap(sizeof(Array) + (t->size*sz));
  373. h->t = &Tarray;
  374. Tarray.ref++;
  375. a = H2D(Array*, h);
  376. a->t = t;
  377. a->len = sz;
  378. a->root = H;
  379. a->data = (uchar*)a + sizeof(Array);
  380. initarray(t, a);
  381. return h;
  382. }
  383. int
  384. hmsize(void *v)
  385. {
  386. return poolmsize(heapmem, v);
  387. }
  388. void
  389. initarray(Type *t, Array *a)
  390. {
  391. int i;
  392. uchar *p;
  393. t->ref++;
  394. if(t->np == 0)
  395. return;
  396. p = a->data;
  397. for(i = 0; i < a->len; i++) {
  398. initmem(t, p);
  399. p += t->size;
  400. }
  401. }
  402. void*
  403. arraycpy(Array *sa)
  404. {
  405. int i;
  406. Heap *dh;
  407. Array *da;
  408. uchar *elemp;
  409. void **sp, **dp;
  410. if(sa == H)
  411. return H;
  412. dh = nheap(sizeof(Array) + sa->t->size*sa->len);
  413. dh->t = &Tarray;
  414. Tarray.ref++;
  415. da = H2D(Array*, dh);
  416. da->t = sa->t;
  417. da->t->ref++;
  418. da->len = sa->len;
  419. da->root = H;
  420. da->data = (uchar*)da + sizeof(Array);
  421. if(da->t == &Tarray) {
  422. dp = (void**)da->data;
  423. sp = (void**)sa->data;
  424. /*
  425. * Maximum depth of this recursion is set by DADEPTH
  426. * in include/isa.h
  427. */
  428. for(i = 0; i < sa->len; i++)
  429. dp[i] = arraycpy(sp[i]);
  430. }
  431. else {
  432. memmove(da->data, sa->data, da->len*sa->t->size);
  433. elemp = da->data;
  434. for(i = 0; i < sa->len; i++) {
  435. incmem(elemp, da->t);
  436. elemp += da->t->size;
  437. }
  438. }
  439. return da;
  440. }
  441. void
  442. newmp(void *dst, void *src, Type *t)
  443. {
  444. Heap *h;
  445. int c, i, m;
  446. void **uld, *wp, **q;
  447. memmove(dst, src, t->size);
  448. uld = dst;
  449. for(i = 0; i < t->np; i++) {
  450. c = t->map[i];
  451. if(c != 0) {
  452. m = 0x80;
  453. q = uld;
  454. while(m != 0) {
  455. if((m & c) && (wp = *q) != H) {
  456. h = D2H(wp);
  457. if(h->t == &Tarray)
  458. *q = arraycpy(wp);
  459. else {
  460. h->ref++;
  461. Setmark(h);
  462. }
  463. }
  464. m >>= 1;
  465. q++;
  466. }
  467. }
  468. uld += 8;
  469. }
  470. }