PageRenderTime 58ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/src/spvw_garcol.d

https://github.com/ynd/clisp-branch--ynd-devel
D | 2539 lines | 2015 code | 58 blank | 466 comment | 421 complexity | a359c07cd23040c499f64212b36cd870 MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /* Garbage collector. */
  2. /* --------------------------- Specification --------------------------- */
  3. /* Execute a simple garbage collection.
  4. can trigger GC */
  5. local maygc void gar_col_simple (void);
  6. /* Execute a full garbage collection.
  7. > level: if 1, also drop all jitc code
  8. can trigger GC */
  9. global maygc void gar_col (int level);
  10. #ifdef SPVW_PAGES
  11. /* Supplement a simple garbage collection with a compacting.
  12. can trigger GC */
  13. local maygc void gar_col_compact (void);
  14. #endif
  15. #if defined(SPVW_MIXED_BLOCKS_OPPOSITE) && RESERVE
  16. /* Move the conses, to make a little more room. */
  17. local void move_conses (sintM delta);
  18. #endif
  19. /* --------------------------- Implementation -------------------------- */
  20. /* overall strategy:
  21. 1. pseudo-recursive marking by setting of garcol_bit.
  22. 2. relocate objects of fixed length (conses and similar),
  23. calculation of displacement of objects of variable length.
  24. 3. update of pointers.
  25. 4. perform the displacements of objects of variable length.
  26. */
  27. #include "spvw_genera1.c"
  28. /* marking-subroutine
  29. procedure: marking routine without stack usage (i.e.
  30. non-"recursive") by descent into the structure to be marked
  31. with pointer-modification (pointers are reversed,
  32. so that they can serve as "ariadne thread")
  33. Convention: an object X counts as marked, if
  34. - an object of variable length: bit garcol_bit,(X) is set
  35. - a two-pointer-object: bit garcol_bit,(X) is set
  36. - a SUBR/FSUBR: bit garcol_bit,(X+const_offset) is set
  37. - Character, Short-Float, Fixnum etc.: always. */
  38. #if DEBUG_GC_MARK
  39. #define IF_DEBUG_GC_MARK(statement) statement
  40. #if defined(WIDE_SOFT) || defined(WIDE_AUXI)
  41. /* oint is defined as uint64. */
  42. #define PRIoint "ll"
  43. #else
  44. /* oint is defined as uintP. Assume pointer_bitsize == long_bitsize. */
  45. #define PRIoint "l"
  46. #endif
  47. #else
  48. #define IF_DEBUG_GC_MARK(statement) /*nop*/
  49. #endif
  50. #define MARK(obj) mark(obj)
  51. #include "spvw_gcmark.c"
  52. #undef MARK
  53. /* pack a pointer into an object, without typeinfo.
  54. pointer_as_object(ptr): void* --> object
  55. pointer_was_object(obj): object --> void* */
  56. #ifdef TYPECODES
  57. #define pointer_as_object(ptr) type_pointer_object(0,ptr)
  58. #define pointer_was_object(obj) type_pointable(0,obj)
  59. #else
  60. #if defined(WIDE_AUXI)
  61. #define pointer_as_object(ptr) as_object_with_auxi((aint)(ptr))
  62. #define pointer_was_object(obj) ((void*)((obj).one_o))
  63. #else
  64. #define pointer_as_object(ptr) as_object((oint)(ptr))
  65. #define pointer_was_object(obj) ((void*)as_oint(obj))
  66. #endif
  67. #endif
  68. /* marking phase:
  69. All "active" structures are marked.
  70. everything is active, that is reachable
  71. - from the LISP-stack or
  72. - at Generational-GC: from the old generation or
  73. - as program-constant (the list of all packages belongs to this). */
  74. local void gc_mark_stack (gcv_object_t* objptr)
  75. {
  76. while (!eq(*objptr,nullobj)) { /* until STACK is finished: */
  77. IF_DEBUG_GC_MARK(fprintf(stderr,"gc_mark_stack: 0x%lx/%lu (%lu)\n",
  78. objptr,objptr,as_oint(*objptr)));
  79. if (as_oint(*objptr) & wbit(frame_bit_o)) { /* does a frame start here? */
  80. if ((as_oint(*objptr) & wbit(skip2_bit_o)) == 0) /* without skip2-Bit? */
  81. objptr skipSTACKop 2; /* yes -> advance by 2 */
  82. else
  83. objptr skipSTACKop 1; /* no -> advance by 1 */
  84. } else { /* normal object, mark: */
  85. var object obj = *objptr;
  86. #ifndef NO_symbolflags
  87. switch (typecode(obj)) { /* poss. remove Symbol-flags */
  88. case_symbolflagged:
  89. obj = symbol_without_flags(obj);
  90. default: break;
  91. }
  92. #endif
  93. gc_mark(obj);
  94. objptr skipSTACKop 1; /* advance */
  95. }
  96. }
  97. }
  98. #include "spvw_genera2.c"
  99. local void gc_markphase (void)
  100. {
  101. /* Mark all the STACKs */
  102. for_all_STACKs(gc_mark_stack(objptr));
  103. #ifdef GENERATIONAL_GC
  104. /* mark old generation, whereas it is perused sparingly: */
  105. if (generation > 0) { gc_mark_old_generation(); }
  106. #endif
  107. /* mark all program constants: */
  108. #if !defined(GENERATIONAL_GC)
  109. for_all_subrs(gc_mark(subr_tab_ptr_as_object(ptr));); /* subr_tab */
  110. for_all_constsyms(gc_mark(symbol_tab_ptr_as_object(ptr));); /* symbol_tab */
  111. #else
  112. /* Because of the macro in_old_generation(), gc_mark() may regard all
  113. constant symbols and all subrs as belonging to the old generation and
  114. may not walk through their pointers recursively. So do it by hand. */
  115. for_all_subrs({ /* peruse subr_tab */
  116. gc_mark(ptr->name);
  117. gc_mark(ptr->keywords);
  118. });
  119. for_all_constsyms({ /* peruse symbol_tab */
  120. gc_mark(ptr->symvalue);
  121. gc_mark(ptr->symfunction);
  122. gc_mark(ptr->hashcode);
  123. gc_mark(ptr->proplist);
  124. gc_mark(ptr->pname);
  125. gc_mark(ptr->homepackage);
  126. });
  127. #endif
  128. for_all_constobjs( gc_mark(*objptr); ); /* object_tab */
  129. for_all_threadobjs( gc_mark(*objptr); ); /* threads */
  130. /* The callers in back_trace are mostly already marked:
  131. they refer to subrs and closures that are currently being
  132. called and therefore cannot possibly be garbage-collected.
  133. But a few remain unmarked, so make sure all are really marked: */
  134. for_all_back_traces({
  135. for (; bt != NULL; bt = bt->bt_next)
  136. gc_mark(bt->bt_function);
  137. });
  138. }
  139. /* UP: Determine, if an object is still "live".
  140. I.e. if the mark bit is set after the marking phase. */
  141. local bool alive (object obj)
  142. {
  143. #ifdef TYPECODES
  144. switch (typecode(obj)) { /* according to type */
  145. case_pair: /* Cons */
  146. if (in_old_generation(obj,typecode(obj),1)) return true;
  147. if (marked(ThePointer(obj))) return true; else return false;
  148. case_symbol: /* Symbol */
  149. case_array: /* Array */
  150. case_bignum: /* Bignum */
  151. #ifndef IMMEDIATE_FFLOAT
  152. case_ffloat: /* Single-Float */
  153. #endif
  154. case_dfloat: /* Double-Float */
  155. case_lfloat: /* Long-Float */
  156. case_record: /* Record */
  157. if (in_old_generation(obj,typecode(obj),0)) return true;
  158. if (marked(ThePointer(obj))) return true; else return false;
  159. case_subr: /* Subr */
  160. if (marked(TheSubr(obj))) return true; else return false;
  161. case_machine: /* Machine Pointer */
  162. case_char: /* Character */
  163. case_system: /* Frame-pointer, Small-Read-label, system */
  164. case_fixnum: /* Fixnum */
  165. case_sfloat: /* Short-Float */
  166. #ifdef IMMEDIATE_FFLOAT
  167. case_ffloat: /* Single-Float */
  168. #endif
  169. return true;
  170. default:
  171. /* these are no objects. */
  172. /*NOTREACHED*/ abort();
  173. }
  174. #else
  175. switch (as_oint(obj) & nonimmediate_heapcode_mask) {
  176. case varobject_bias+varobjects_misaligned:
  177. if (in_old_generation(obj,,0)) return true;
  178. if (marked(ThePointer(obj))) return true; else return false;
  179. case cons_bias+conses_misaligned:
  180. #ifdef STANDARD_HEAPCODES
  181. /* NB: (immediate_bias & nonimmediate_heapcode_mask) == cons_bias. */
  182. if (immediate_object_p(obj)) return true;
  183. #endif
  184. if (in_old_generation(obj,,1)) return true;
  185. if (marked(ThePointer(obj))) return true; else return false;
  186. #ifdef STANDARD_HEAPCODES
  187. case subr_bias:
  188. if (marked(TheSubr(obj))) return true; else return false;
  189. #endif
  190. default:
  191. return true;
  192. }
  193. #endif
  194. }
  195. #include "spvw_weak.c"
  196. /* unmark SUBRs and fixed Symbols: */
  197. local void unmark_fixed_varobjects (void)
  198. {
  199. /* Even if defined(GENERATIONAL_GC), because the macro in_old_generation()
  200. has undefined behaviour for constsyms and subrs, therefore we don't know
  201. a priori whether the constsyms and subrs have their mark bit set. */
  202. for_all_subrs( unmark(&((Subr)ptr)->GCself); ); /* unmark each Subr */
  203. for_all_constsyms( unmark(&((Symbol)ptr)->GCself); ); /* unmark each Symbol in symbol_tab */
  204. }
  205. #if !defined(MORRIS_GC)
  206. #ifdef SPVW_MIXED_BLOCKS_OPPOSITE
  207. /* concentrate CONS-cells between page->page_start and page->page_end
  208. aloft: */
  209. local void gc_compact_cons_page (Page* page)
  210. {
  211. /* the pointer p1 moves from below and the pointer p2 from
  212. above through the memory region, while (!)they collide.
  213. Marked structures are moved above unmarked. */
  214. var aint p1 = page->page_start; /* lower bound */
  215. var aint p2 = page->page_end; /* upper bound */
  216. sweeploop:
  217. /* search the next-higher unmarked cell <p2 and unmark all: */
  218. sweeploop1:
  219. if (p1==p2) goto sweepok2; /* bounds are equal -> finished */
  220. p2 -= sizeof(cons_); /* capture next cell from above */
  221. if (marked(p2)) { /* marked? */
  222. unmark(p2); /* unmark */
  223. goto sweeploop1;
  224. }
  225. /* p1 <= p2, p2 points to an unmarked cell.
  226. search next lower marked cell >=p1: */
  227. sweeploop2:
  228. if (p1==p2) goto sweepok1; /* bounds are equal -> finished */
  229. if (!marked(p1)) { /* unmarked? */
  230. p1 += sizeof(cons_); /* at the next lower cell */
  231. goto sweeploop2; /* continue search */
  232. }
  233. /* p1 < p2, p1 points to a marked cell. */
  234. unmark(p1); /* unmark */
  235. /* copy content of cell into the unmark cell: */
  236. ((gcv_object_t*)p2)[0] = ((gcv_object_t*)p1)[0];
  237. ((gcv_object_t*)p2)[1] = ((gcv_object_t*)p1)[1];
  238. *(gcv_object_t*)p1 = pointer_as_object(p2); /* leave new addresse */
  239. mark(p1); /* and mark (as identification for the update) */
  240. p1 += sizeof(cons_); /* this cell is finished. */
  241. goto sweeploop; /* continue */
  242. sweepok1: p1 += sizeof(cons_); /* skip last unmarked Cons */
  243. sweepok2:
  244. /* p1 = new lower bound of the Cons-region */
  245. page->page_start = p1;
  246. }
  247. #else
  248. /* concentrate CONS-cells between page->page_start and page->page_end
  249. below: */
  250. local void gc_compact_cons_page (Page* page)
  251. {
  252. /* the pointer p1 moves from below and the pointer p2 from
  253. above through the memory region, while (!)they collide.
  254. Marked structures are moved above unmarked. */
  255. var aint p1 = page->page_start; /* lower bound */
  256. var aint p2 = page->page_end; /* upper bound */
  257. sweeploop:
  258. /* search next higher marked cell <p2: */
  259. sweeploop1:
  260. if (p1==p2) goto sweepok2; /* bounds are equal -> finished */
  261. p2 -= sizeof(cons_); /* capture next cell from above */
  262. if (!marked(p2)) goto sweeploop1; /* unmarked? */
  263. /* p1 <= p2, p2 points to a marked cell. */
  264. unmark(p2); /* unmark */
  265. /* search next lower unmarked cell >=p1 and unmark all: */
  266. sweeploop2:
  267. if (p1==p2) goto sweepok1; /* bounds are equal -> finished */
  268. if (marked(p1)) { /* marked? */
  269. unmark(p1); /* unmark */
  270. p1 += sizeof(cons_); /* at next upper cell */
  271. goto sweeploop2; /* continue search */
  272. }
  273. /* p1 < p2, p1 points to an unmarked cell.
  274. copy cell content from the marked into the unmark cell: */
  275. ((gcv_object_t*)p1)[0] = ((gcv_object_t*)p2)[0];
  276. ((gcv_object_t*)p1)[1] = ((gcv_object_t*)p2)[1];
  277. *(gcv_object_t*)p2 = pointer_as_object(p1); /* leave new address */
  278. mark(p2); /* and mark (as identification for update) */
  279. p1 += sizeof(cons_); /* this cell is finished. */
  280. goto sweeploop; /* continue */
  281. sweepok1: p1 += sizeof(cons_); /* skip last marked Cons */
  282. sweepok2:
  283. /* p1 = new upper bound of the Cons-region */
  284. page->page_end = p1;
  285. }
  286. #endif
  287. #else /* defined(MORRIS_GC) */
  288. /* Algorithm see:
  289. [F. Lockwood Morris: A time- and space-efficient garbage collection algorithm.
  290. CACM 21,8 (August 1978), 662-665.]
  291. Delete all unmarked CONS-cells and unmark the marked CONS-cells,
  292. so that the mark bit is available for the reverse spointers. */
  293. local void gc_morris1 (Page* page)
  294. {
  295. var aint p1 = page->page_start; /* lower bound */
  296. var aint p2 = page->page_end; /* upper bound */
  297. var aint d = 0; /* also count free memory */
  298. while (p1 != p2) {
  299. if (!marked(p1)) {
  300. ((gcv_object_t*)p1)[0] = nullobj;
  301. ((gcv_object_t*)p1)[1] = nullobj;
  302. d += sizeof(cons_);
  303. } else {
  304. unmark(p1);
  305. #ifdef DEBUG_SPVW
  306. if (eq(((gcv_object_t*)p1)[0],nullobj) || eq(((gcv_object_t*)p1)[1],nullobj))
  307. abort();
  308. #endif
  309. }
  310. p1 += sizeof(cons_); /* this cell is finished. */
  311. }
  312. page->page_gcpriv.d = d; /* store free memory */
  313. }
  314. #ifdef SPVW_MIXED_BLOCKS_OPPOSITE
  315. /* There is only one page with Two-Pointer-Objects. */
  316. local void gc_morris2 (Page* page)
  317. {
  318. /* Each cell within a Cons now contains a list of all
  319. addresses of pointers to this cell, that point to this cell
  320. from a root or from a Varobject.
  321. traverse the undeleted conses from left to right:
  322. (in between, each cell contains a list of all addresses
  323. of pointers to this cell, that point to this cell from a root,
  324. from a varobject or a cons lying further to the left.) */
  325. var aint p1 = page->page_start; /* lower bound */
  326. var aint p2 = p1 + page->page_gcpriv.d; /* later lower bound */
  327. var aint p1limit = page->page_end; /* upper bound */
  328. while (p1 != p1limit) { /* always: p1 <= p2 <= p1limit */
  329. /* both cells of a cons are treated exactly the same. */
  330. var object obj = *(gcv_object_t*)p1;
  331. if (!eq(obj,nullobj)) {
  332. /* p1 is moved to p2. */
  333. #ifdef TYPECODES
  334. /* the so far registered pointers to this cell are updated: */
  335. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  336. obj = without_mark_bit(obj);
  337. var aint p = upointer(obj);
  338. var object next_obj = *(gcv_object_t*)p;
  339. *(gcv_object_t*)p = type_pointer_object(typecode(obj),p2);
  340. obj = next_obj;
  341. }
  342. { /* if the cell contains a pointer "to the right", it is reversed. */
  343. var tint type = typecode(obj);
  344. switch (type) {
  345. case_pair: {
  346. var aint p = upointer(obj);
  347. if (!in_old_generation(obj,type,1) && (p > p1)) {
  348. /* For later update, insert
  349. p1 in the list of pointers to p: */
  350. *(gcv_object_t*)p1 = *(gcv_object_t*)p;
  351. *(gcv_object_t*)p = with_mark_bit(type_pointer_object(type,p1));
  352. break;
  353. }
  354. }
  355. default:
  356. *(gcv_object_t*)p1 = obj;
  357. }
  358. }
  359. #else /* no TYPECODES */
  360. /* the so far registered pointers to this cell are updated: */
  361. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  362. obj = without_mark_bit(obj);
  363. var aint p = (aint)ThePointer(obj);
  364. var object next_obj = *(gcv_object_t*)p;
  365. *(gcv_object_t*)p = as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p2);
  366. obj = next_obj;
  367. }
  368. /* if the cell contains a pointer "to the right", it is reversed. */
  369. if (consp(obj)) {
  370. var aint p = (aint)ThePointer(obj);
  371. if (!in_old_generation(obj,,1) && (p > p1)) {
  372. /* For later update, insert
  373. p1 in the list of pointers to p: */
  374. *(gcv_object_t*)p1 = *(gcv_object_t*)p;
  375. *(gcv_object_t*)p = with_mark_bit(as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p1));
  376. } else {
  377. *(gcv_object_t*)p1 = obj;
  378. }
  379. } else {
  380. *(gcv_object_t*)p1 = obj;
  381. }
  382. #endif
  383. p2 += sizeof(gcv_object_t);
  384. }
  385. p1 += sizeof(gcv_object_t);
  386. }
  387. if (p2!=p1limit)
  388. abort();
  389. }
  390. local void gc_morris3 (Page* page)
  391. {
  392. /* Each cell within a cons now contains again the original content.
  393. Traverse the undeleted conses from right to left
  394. and compact them on the right:
  395. (in between, each cell contains a list of all addresses
  396. of pointers to this cell, that point to this cell
  397. from a cons lying further to the right.) */
  398. var aint p1limit = page->page_start; /* lower bound */
  399. var aint p1 = page->page_end; /* upper bound */
  400. var aint p2 = p1; /* upper bound */
  401. #ifdef DEBUG_SPVW
  402. while (p1!=p1limit) {
  403. p1 -= 2*sizeof(gcv_object_t);
  404. if (eq(*(gcv_object_t*)p1,nullobj)+eq(*(gcv_object_t*)(p1^sizeof(gcv_object_t)),nullobj)==1)
  405. abort();
  406. }
  407. p1 = page->page_end;
  408. #endif
  409. while (p1!=p1limit) { /* always: p1limit <= p1 <= p2 */
  410. /* both cells of a cons are treated exactly the same. */
  411. p1 -= sizeof(gcv_object_t);
  412. #ifdef DEBUG_SPVW
  413. if (eq(*(gcv_object_t*)p1,nullobj)+eq(*(gcv_object_t*)(p1^sizeof(gcv_object_t)),nullobj)==1)
  414. abort();
  415. if (((p1 % (2*sizeof(gcv_object_t))) != 0)
  416. && ((p2 % (2*sizeof(gcv_object_t))) != 0))
  417. abort();
  418. #endif
  419. var object obj = *(gcv_object_t*)p1;
  420. if (!eq(obj,nullobj)) {
  421. p2 -= sizeof(gcv_object_t);
  422. /* p1 is moved to p2. */
  423. #ifdef TYPECODES
  424. /* The newly registered pointers to this cell are updated: */
  425. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  426. obj = without_mark_bit(obj);
  427. var aint p = upointer(obj);
  428. var object next_obj = *(gcv_object_t*)p;
  429. *(gcv_object_t*)p = type_pointer_object(typecode(obj),p2);
  430. obj = next_obj;
  431. }
  432. #ifdef DEBUG_SPVW
  433. if (eq(obj,nullobj)) abort();
  434. #endif
  435. *(gcv_object_t*)p2 = obj;
  436. {
  437. var tint type = typecode(obj);
  438. if (!gcinvariant_type_p(type)) /* un-movable -> do nothing */
  439. switch (type) {
  440. case_pair: { /* Two-Pointer-Object */
  441. var aint p = upointer(obj);
  442. if (p < p1) { /* pointer to the left? */
  443. /* For later update, insert
  444. p2 into the list of pointers to p: */
  445. #ifdef DEBUG_SPVW
  446. if (eq(*(gcv_object_t*)p,nullobj)) abort();
  447. #endif
  448. *(gcv_object_t*)p2 = *(gcv_object_t*)p;
  449. *(gcv_object_t*)p = with_mark_bit(type_pointer_object(type,p2));
  450. } else if (p == p1) { /* pointer to itself? */
  451. *(gcv_object_t*)p2 = type_pointer_object(type,p2);
  452. }
  453. }
  454. break;
  455. default: /* object of variable length */
  456. if (marked(ThePointer(obj))) /* marked? */
  457. *(gcv_object_t*)p2 = type_untype_object(type,untype(*(gcv_object_t*)ThePointer(obj)));
  458. break;
  459. }
  460. }
  461. #else /* no TYPECODES */
  462. /* The newly registered pointers to this cell are updated: */
  463. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  464. obj = without_mark_bit(obj);
  465. var aint p = (aint)ThePointer(obj);
  466. var object next_obj = *(gcv_object_t*)p;
  467. *(gcv_object_t*)p = as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p2);
  468. obj = next_obj;
  469. }
  470. #ifdef DEBUG_SPVW
  471. if (eq(obj,nullobj)) abort();
  472. #endif
  473. *(gcv_object_t*)p2 = obj;
  474. if (!gcinvariant_object_p(obj)) { /* un-movable -> do nothing */
  475. if (consp(obj)) {
  476. /* Two-Pointer-Object */
  477. var aint p = (aint)ThePointer(obj);
  478. if (p < p1) { /* pointer to the left? */
  479. /* for later update, insert
  480. p2 into the list of pointers to p: */
  481. #ifdef DEBUG_SPVW
  482. if (eq(*(gcv_object_t*)p,nullobj)) abort();
  483. #endif
  484. *(gcv_object_t*)p2 = *(gcv_object_t*)p;
  485. *(gcv_object_t*)p = with_mark_bit(as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p2));
  486. } else if (p == p1) { /* pointer to itself? */
  487. *(gcv_object_t*)p2 = as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p2);
  488. }
  489. } else {
  490. /* object of variable length */
  491. if (marked(ThePointer(obj))) /* marked? */
  492. *(gcv_object_t*)p2 = as_object((as_oint(obj) & nonimmediate_bias_mask) | (as_oint(*(gcv_object_t*)ThePointer(obj)) & ~wbit(garcol_bit_o) & ~(oint)nonimmediate_bias_mask));
  493. }
  494. }
  495. #endif
  496. }
  497. }
  498. /* p2 = new lower bound of the Cons-region */
  499. if (p2 != page->page_start + page->page_gcpriv.d)
  500. abort();
  501. page->page_start = p2;
  502. }
  503. #elif defined(SPVW_MIXED_BLOCKS_STAGGERED)
  504. local void gc_morris2 (Page* page)
  505. {
  506. /* Each cell within a Cons now contains a list of all
  507. addresses of pointers to this cell, that point to this cell
  508. from a root or from a Varobject.
  509. Traverse the undeleted conses from right to left:
  510. (in between, each cell contains a liste of all addresses
  511. of pointers to this cell, that point to this cell from a root,
  512. from a varobject or a cons lying further to the right.) */
  513. var aint p1 = page->page_end; /* upper bound */
  514. var aint p2 = p1 - page->page_gcpriv.d; /* later upper bound */
  515. var aint p1limit = page->page_start; /* lower bound */
  516. #ifdef DEBUG_SPVW
  517. while (p1!=p1limit) {
  518. p1 -= 2*sizeof(gcv_object_t);
  519. if (eq(*(gcv_object_t*)p1,nullobj)+eq(*(gcv_object_t*)(p1^sizeof(gcv_object_t)),nullobj)==1)
  520. abort();
  521. }
  522. p1 = page->page_end;
  523. #endif
  524. while (p1!=p1limit) { /* always: p1limit <= p2 <= p1 */
  525. /* both cells of a cons are treated exactly the same. */
  526. p1 -= sizeof(gcv_object_t);
  527. #ifdef DEBUG_SPVW
  528. if (eq(*(gcv_object_t*)p1,nullobj)+eq(*(gcv_object_t*)(p1^sizeof(gcv_object_t)),nullobj)==1)
  529. abort();
  530. #endif
  531. var object obj = *(gcv_object_t*)p1;
  532. if (!eq(obj,nullobj)) {
  533. p2 -= sizeof(gcv_object_t);
  534. /* p1 is moved to p2. */
  535. #ifdef TYPECODES
  536. /* the so far registered pointers to this cell are updated: */
  537. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  538. obj = without_mark_bit(obj);
  539. var aint p = upointer(obj);
  540. var object next_obj = *(gcv_object_t*)p;
  541. *(gcv_object_t*)p = type_pointer_object(typecode(obj),p2);
  542. obj = next_obj;
  543. }
  544. /* obj = original content of the cell p1. */
  545. #ifdef DEBUG_SPVW
  546. if (eq(obj,nullobj)) abort();
  547. #endif
  548. /* if the cell contains a pointer "to the left", it is reversed. */
  549. {
  550. var tint type = typecode(obj);
  551. switch (type) {
  552. case_pair: {
  553. var aint p = upointer(obj);
  554. if (!in_old_generation(obj,type,1) && (p < p1)) {
  555. /* For later update, insert
  556. p1 into the list of pointers to p: */
  557. *(gcv_object_t*)p1 = *(gcv_object_t*)p;
  558. *(gcv_object_t*)p = with_mark_bit(type_pointer_object(type,p1));
  559. break;
  560. }
  561. }
  562. default:
  563. *(gcv_object_t*)p1 = obj;
  564. }
  565. }
  566. #else
  567. /* the so far registered pointers to this cell are updated: */
  568. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  569. obj = without_mark_bit(obj);
  570. var aint p = (aint)ThePointer(obj);
  571. var object next_obj = *(gcv_object_t*)p;
  572. *(gcv_object_t*)p = as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p2);
  573. obj = next_obj;
  574. }
  575. /* obj = original content of the cell p1. */
  576. #ifdef DEBUG_SPVW
  577. if (eq(obj,nullobj)) abort();
  578. #endif
  579. /* if the cell contains a pointer "to the left", it is reversed. */
  580. if (consp(obj)) {
  581. var aint p = (aint)ThePointer(obj);
  582. if (!in_old_generation(obj,,1) && (p < p1)) {
  583. /* For later update, insert
  584. p1 into the list of pointers to p: */
  585. *(gcv_object_t*)p1 = *(gcv_object_t*)p;
  586. *(gcv_object_t*)p = with_mark_bit(as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p1));
  587. } else {
  588. *(gcv_object_t*)p1 = obj;
  589. }
  590. } else {
  591. *(gcv_object_t*)p1 = obj;
  592. }
  593. #endif
  594. }
  595. }
  596. if (p2!=p1limit)
  597. abort();
  598. }
  599. local void gc_morris3 (Page* page)
  600. {
  601. /* Each cell within a cons now contains again the original content.
  602. Traverse the undeleted conses from left to right
  603. and compact them on the left:
  604. (in between, each cell contains a list of all addresses
  605. of pointers to this cell, that point to this cell
  606. from a cons lying further to the left.) */
  607. var aint p1limit = page->page_end; /* obere Grenze */
  608. var aint p1 = page->page_start; /* lower bound */
  609. var aint p2 = p1; /* lower bound */
  610. while (p1!=p1limit) { /* always: p1limit <= p1 <= p2 */
  611. /* both cells of a cons are treated exactly the same. */
  612. var object obj = *(gcv_object_t*)p1;
  613. if (!eq(obj,nullobj)) {
  614. /* p1 is moved to p2. */
  615. #ifdef TYPECODES
  616. /* The newly registered pointers to this cell are updated: */
  617. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  618. obj = without_mark_bit(obj);
  619. var aint p = upointer(obj);
  620. var object next_obj = *(gcv_object_t*)p;
  621. *(gcv_object_t*)p = type_pointer_object(typecode(obj),p2);
  622. obj = next_obj;
  623. }
  624. /* obj = true content of the cell p1. */
  625. {
  626. var tint type = typecode(obj);
  627. if (!gcinvariant_type_p(type)) /* un-movable -> do nothing */
  628. switch (type) {
  629. case_pair: { /* Two-Pointer-Object */
  630. var aint p = upointer(obj);
  631. if (p > p1) { /* pointer to the right? */
  632. /* For later update, insert
  633. p2 into the list of pointers to p: */
  634. #ifdef DEBUG_SPVW
  635. if (eq(*(gcv_object_t*)p,nullobj)) abort();
  636. #endif
  637. *(gcv_object_t*)p2 = *(gcv_object_t*)p;
  638. *(gcv_object_t*)p = with_mark_bit(type_pointer_object(type,p2));
  639. } else if (p == p1) { /* Pointer to itself? */
  640. *(gcv_object_t*)p2 = type_pointer_object(type,p2);
  641. } else {
  642. *(gcv_object_t*)p2 = obj;
  643. }
  644. }
  645. break;
  646. default: /* object of variable length */
  647. if (marked(ThePointer(obj))) /* marked? */
  648. *(gcv_object_t*)p2 = type_untype_object(type,untype(*(gcv_object_t*)ThePointer(obj)));
  649. else
  650. *(gcv_object_t*)p2 = obj;
  651. break;
  652. }
  653. else { /* un-movable or pointer into the old generation -> do nothing */
  654. *(gcv_object_t*)p2 = obj;
  655. }
  656. }
  657. #else
  658. /* The newly registered pointers to this cell are updated: */
  659. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  660. obj = without_mark_bit(obj);
  661. var aint p = (aint)ThePointer(obj);
  662. var object next_obj = *(gcv_object_t*)p;
  663. *(gcv_object_t*)p = as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p2);
  664. obj = next_obj;
  665. }
  666. /* obj = true content of the cell p1. */
  667. if (!gcinvariant_object_p(obj)) { /* un-movable -> do nothing */
  668. if (consp(obj)) {
  669. /* Two-Pointer-Object */
  670. var aint p = (aint)ThePointer(obj);
  671. if (p > p1) { /* pointer to the right? */
  672. /* For later update, insert
  673. p2 into the list of pointers to p: */
  674. #ifdef DEBUG_SPVW
  675. if (eq(*(gcv_object_t*)p,nullobj)) abort();
  676. #endif
  677. *(gcv_object_t*)p2 = *(gcv_object_t*)p;
  678. *(gcv_object_t*)p = with_mark_bit(as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p2));
  679. } else if (p == p1) { /* pointer to itself? */
  680. *(gcv_object_t*)p2 = as_object((as_oint(obj) & nonimmediate_bias_mask) | (oint)p2);
  681. } else {
  682. *(gcv_object_t*)p2 = obj;
  683. }
  684. } else {
  685. /* Object of variable length */
  686. if (marked(ThePointer(obj))) /* marked? */
  687. *(gcv_object_t*)p2 = as_object((as_oint(obj) & nonimmediate_bias_mask) | (as_oint(*(gcv_object_t*)ThePointer(obj)) & ~wbit(garcol_bit_o) & ~(oint)nonimmediate_bias_mask));
  688. else
  689. *(gcv_object_t*)p2 = obj;
  690. }
  691. } else { /* un-movable or pointer into the old generation -> do nothing */
  692. *(gcv_object_t*)p2 = obj;
  693. }
  694. #endif
  695. p2 += sizeof(gcv_object_t);
  696. }
  697. p1 += sizeof(gcv_object_t);
  698. }
  699. /* p2 = new upper bound of the Cons-region */
  700. if (p2 != page->page_end - page->page_gcpriv.d)
  701. abort();
  702. page->page_end = p2;
  703. }
  704. #else /* SPVW_PURE_BLOCKS <==> SINGLEMAP_MEMORY */
  705. /* gc_morris2 and gc_morris3 must be called for each page exactly once,
  706. first gc_morris2 from right to left, then gc_morris3 from left to right
  707. (in terms of the positioning of the addresses)! */
  708. local void gc_morris2 (Page* page)
  709. {
  710. /* Each cell within a Cons now contains a list of all
  711. addresses of pointers to this cell, that point to this cell
  712. from a root or from a Varobject.
  713. Traverse the undeleted conses from right to left:
  714. (in between, each cell contains a liste of all addresses
  715. of pointers to this cell, that point to this cell from a root,
  716. from a varobject or a cons lying further to the right.) */
  717. var aint p1 = page->page_end; /* upper bound */
  718. var aint p2 = p1 - page->page_gcpriv.d; /* later upper bound */
  719. var aint p1limit = page->page_start; /* lower bound */
  720. while (p1!=p1limit) { /* always: p1limit <= p2 <= p1 */
  721. /* both cells of a cons are treated exactly the same. */
  722. p1 -= sizeof(gcv_object_t);
  723. var object obj = *(gcv_object_t*)p1;
  724. if (!eq(obj,nullobj)) {
  725. p2 -= sizeof(gcv_object_t);
  726. /* p1 is moved to p2.
  727. the so far registered pointers to this cell are updated: */
  728. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  729. obj = without_mark_bit(obj);
  730. var object next_obj = *(gcv_object_t*)pointable(obj);
  731. *(gcv_object_t*)pointable(obj) = as_object(p2);
  732. obj = next_obj;
  733. }
  734. /* obj = original content of the cell p1.
  735. if the cell contains a pointer "to the left", it is reversed. */
  736. if (is_cons_heap(typecode(obj))
  737. && !in_old_generation(obj,typecode(obj),1)
  738. && ((aint)pointable(obj) < p1)
  739. ) {
  740. /* For later update, insert
  741. p1 into the list of pointers to obj: */
  742. *(gcv_object_t*)p1 = *(gcv_object_t*)pointable(obj);
  743. *(gcv_object_t*)pointable(obj) = with_mark_bit(as_object(p1));
  744. } else {
  745. *(gcv_object_t*)p1 = obj;
  746. }
  747. }
  748. }
  749. if (p2!=p1limit)
  750. abort();
  751. }
  752. local void gc_morris3 (Page* page)
  753. {
  754. /* Each cell within a cons now contains again the original content.
  755. Traverse the undeleted conses from left to right
  756. and compact them on the left:
  757. (in between, each cell contains a list of all addresses
  758. of pointers to this cell, that point to this cell
  759. from a cons lying further to the left.) */
  760. var aint p1limit = page->page_end; /* upper bound */
  761. var aint p1 = page->page_start; /* lower bound */
  762. var aint p2 = p1; /* lower bound */
  763. while (p1!=p1limit) { /* always: p1limit <= p1 <= p2 */
  764. /* both cells of a cons are treated exactly the same. */
  765. var object obj = *(gcv_object_t*)p1;
  766. if (!eq(obj,nullobj)) {
  767. /* p1 is moved to p2.
  768. The newly registered pointers to this cell are updated: */
  769. while ((as_oint(obj) & wbit(garcol_bit_o)) != 0) { /* process list */
  770. obj = without_mark_bit(obj);
  771. var object next_obj = *(gcv_object_t*)pointable(obj);
  772. *(gcv_object_t*)pointable(obj) = as_object(p2);
  773. obj = next_obj;
  774. }
  775. /* obj = true content of cell p1. */
  776. {
  777. var tint type = typecode(obj);
  778. if (!is_unused_heap(type) && !in_old_generation(obj,type,?))
  779. if (is_cons_heap(type)) {
  780. /* Two-Pointer-Object */
  781. if ((aint)pointable(obj) > p1) { /* pointer to the right? */
  782. /* For later update, insert
  783. p2 into the list of pointers to obj: */
  784. *(gcv_object_t*)p2 = *(gcv_object_t*)pointable(obj);
  785. *(gcv_object_t*)pointable(obj) = with_mark_bit(as_object(p2));
  786. } else if ((aint)pointable(obj) == p1) { /* pointer to itself? */
  787. *(gcv_object_t*)p2 = as_object(p2);
  788. } else {
  789. *(gcv_object_t*)p2 = obj;
  790. }
  791. } else {
  792. /* object of variable length */
  793. if (marked(ThePointer(obj))) /* marked? */
  794. *(gcv_object_t*)p2 = type_untype_object(type,untype(*(gcv_object_t*)ThePointer(obj)));
  795. else
  796. *(gcv_object_t*)p2 = obj;
  797. } else { /* un-movable or pointer into the old generation -> do nothing */
  798. *(gcv_object_t*)p2 = obj;
  799. }
  800. }
  801. p2 += sizeof(gcv_object_t);
  802. }
  803. p1 += sizeof(gcv_object_t);
  804. }
  805. /* p2 = new upper bound of the Cons-region */
  806. if (p2 != page->page_end - page->page_gcpriv.d)
  807. abort();
  808. page->page_end = p2;
  809. }
  810. #endif
  811. #endif
  812. /* modify the self-pointer of an object of variable length:
  813. set_GCself(p,type,addr);
  814. sets p->GCself to type_pointer_object(type,addr). */
  815. #ifdef TYPECODES
  816. #if !(exact_uint_size_p(oint_type_len) && ((oint_type_shift%hfintsize)==0) && (tint_type_mask == bit(oint_type_len)-1))
  817. #ifdef MAP_MEMORY
  818. /* addr contains typeinfo */
  819. #define make_GCself(type,addr) \
  820. type_pointer_object((type)&(tint_type_mask),(addr)&(oint_addr_mask))
  821. #else
  822. /* addr contains no typeinfo */
  823. #define make_GCself(type,addr) \
  824. type_pointer_object((type)&(tint_type_mask),addr)
  825. #endif
  826. #define set_GCself(p,type,addr) \
  827. ((Varobject)(p))->GCself = make_GCself(type,addr)
  828. #else /* better: though two memory accesses, but less arithmetics */
  829. #define make_GCself(type,addr) \
  830. type_pointer_object((type)&(tint_type_mask),(addr)&~(oint_type_mask))
  831. #define set_GCself(p,type,addr) \
  832. (((Varobject)(p))->GCself = type_pointer_object(0,addr), \
  833. ((Varobject)(p))->header_flags = (type))
  834. #endif
  835. #else
  836. #define make_GCself(type,addr) /* ignore type */ \
  837. as_object((oint)(addr))
  838. #define set_GCself(p,type,addr) /* ignore type */ \
  839. ((Varobject)(p))->GCself = make_GCself(type,addr)
  840. #endif
  841. #ifdef HAVE_SMALL_SSTRING
  842. /* Special handling of forward pointers among simple-strings. */
  843. local void gc_sweep1_sstring_forward (aint p2) {
  844. var gcv_object_t forward = ((Sistring)p2)->data;
  845. if (sstring_flags(TheSstring(forward)) & sstringflags_relocated_B) {
  846. var gcv_object_t target = TheSstring(forward)->GCself;
  847. var aint backchain = p2;
  848. for (;;) {
  849. var gcv_object_t backpointer = ((Varobject)backchain)->GCself;
  850. ((Varobject)backchain)->GCself = target;
  851. sstring_flags_set((Sstring)backchain,sstringflags_relocated_B);
  852. if (sstring_flags((Sstring)backchain) & sstringflags_backpointer_B)
  853. backchain = (aint)ThePointer(without_mark_bit(backpointer));
  854. else
  855. break;
  856. }
  857. } else {
  858. /* Leave a backpointer for later fixup.
  859. Each string can have only one forward pointer directly pointing
  860. to it. This ensures that the backchain is a singly linked list. */
  861. if (sstring_flags(TheSstring(forward)) & sstringflags_backpointer_B)
  862. /*NOTREACHED*/ abort();
  863. TheSstring(forward)->GCself = with_mark_bit(make_GCself(sstring_type,p2));
  864. sstring_flags_set(TheSstring(forward),sstringflags_backpointer_B);
  865. }
  866. /* Don't reclaim the space at p2 during this GC, because
  867. 1. we need the mark bit at p2 so that update() does the
  868. relocation, and the mark bit tells gc_sweep2_varobject_page
  869. that the object is not yet reclaimed.
  870. 2. otherwise last_open_ptr may be set to &((Varobject)p2)->GCself
  871. later. */
  872. }
  873. local void gc_sweep1_sstring_target (aint p2, aint p1) {
  874. if (sstring_flags((Sstring)p2) & sstringflags_relocated_B)
  875. /*NOTREACHED*/ abort();
  876. var gcv_object_t target; target = with_mark_bit(make_GCself(sstring_type,p1));
  877. var aint backchain = p2;
  878. for (;;) {
  879. var gcv_object_t backpointer = ((Varobject)backchain)->GCself;
  880. ((Varobject)backchain)->GCself = target;
  881. sstring_flags_set((Sstring)backchain,sstringflags_relocated_B);
  882. if (sstring_flags((Sstring)backchain) & sstringflags_backpointer_B)
  883. backchain = (aint)ThePointer(without_mark_bit(backpointer));
  884. else
  885. break;
  886. }
  887. }
  888. #endif
  889. /* Special handling of forward pointers among CLOS instances. */
  890. local void gc_sweep1_instance_forward (aint p2) {
  891. var gcv_object_t forward = ((Instance)p2)->inst_class_version;
  892. if (record_flags(TheInstance(forward)) & instflags_relocated_B) {
  893. var gcv_object_t target = TheInstance(forward)->GCself;
  894. var aint backchain = p2;
  895. for (;;) {
  896. var gcv_object_t backpointer = ((Varobject)backchain)->GCself;
  897. ((Varobject)backchain)->GCself = target;
  898. record_flags_set((Record)backchain,instflags_relocated_B);
  899. if (record_flags((Record)backchain) & instflags_backpointer_B)
  900. backchain = (aint)ThePointer(without_mark_bit(backpointer));
  901. else
  902. break;
  903. }
  904. } else {
  905. /* Leave a backpointer for later fixup.
  906. Each instance can have only one forward pointer directly pointing
  907. to it. This ensures that the backchain is a singly linked list. */
  908. if (record_flags(TheInstance(forward)) & instflags_backpointer_B)
  909. /*NOTREACHED*/ abort();
  910. #ifdef TYPECODES
  911. /* The type is either instance_type or closure_type. */
  912. var tint type = mtypecode(((Varobject)p2)->GCself) & ~bit(garcol_bit_t);
  913. #endif
  914. TheInstance(forward)->GCself = with_mark_bit(make_GCself(type,p2));
  915. record_flags_set(TheInstance(forward),instflags_backpointer_B);
  916. }
  917. /* Don't reclaim the space at p2 during this GC, because
  918. 1. we need the mark bit at p2 so that update() does the
  919. relocation, and the mark bit tells gc_sweep2_varobject_page
  920. that the object is not yet reclaimed.
  921. 2. otherwise last_open_ptr may be set to &((Varobject)p2)->GCself
  922. later. */
  923. }
  924. local void gc_sweep1_instance_target (aint p2, aint p1) {
  925. if (record_flags((Instance)p2) & instflags_relocated_B)
  926. /*NOTREACHED*/ abort();
  927. #ifdef TYPECODES
  928. /* The type is either instance_type or closure_type. */
  929. var tint type = mtypecode(((Varobject)p2)->GCself) & ~bit(garcol_bit_t);
  930. #endif
  931. var gcv_object_t target; target = with_mark_bit(make_GCself(type,p1));
  932. var aint backchain = p2;
  933. for (;;) {
  934. var gcv_object_t backpointer = ((Varobject)backchain)->GCself;
  935. ((Varobject)backchain)->GCself = target;
  936. record_flags_set((Record)backchain,instflags_relocated_B);
  937. if (record_flags((Record)backchain) & instflags_backpointer_B)
  938. backchain = (aint)ThePointer(without_mark_bit(backpointer));
  939. else
  940. break;
  941. }
  942. }
  943. /* Prepare objects of variable length between page->page_start and
  944. page->page_end for compacting below. Therefore, in each marked
  945. object the pointer in front is pointed to the location, where the
  946. object will be located later (including typeinfo). If the sequencing
  947. object is unmarked, then its first pointer is oriented to the address
  948. of the next marked object. */
  949. #ifdef SPVW_PURE
  950. local aint gc_sweep1_varobject_page (uintL heapnr, aint start, aint end, gcv_object_t* firstmarked, aint dest)
  951. #elif defined(GENERATIONAL_GC)
  952. local aint gc_sweep1_varobject_page (aint start, aint end, gcv_object_t* firstmarked, aint dest)
  953. #else
  954. local void gc_sweep1_varobject_page (Page* page)
  955. #endif
  956. {
  957. #if defined(SPVW_PURE) || defined(GENERATIONAL_GC)
  958. var gcv_object_t* last_open_ptr = firstmarked;
  959. var aint p2 = start; /* source-pointer */
  960. var aint p2end = end; /* upper bound of the source-region */
  961. var aint p1 = dest; /* destination-pointer */
  962. #else
  963. var gcv_object_t* last_open_ptr = &page->page_gcpriv.firstmarked;
  964. /* In *last_open_ptr, always store the address of the next marked
  965. object (als oint) .
  966. Via chained-list-mechanism: At the end, page->page_gcpriv.firstmarked
  967. contains the address of the 1. marked object */
  968. var aint p2 = page->page_start; /* source-pointer */
  969. var aint p2end = page->page_end; /* upper bound of the source-region */
  970. var aint p1 = p2; /* destination-pointer */
  971. #endif
  972. /* start <= p1 <= p2 <= end, p1 and p2 grow, p2 faster than p1. */
  973. var_prepare_objsize;
  974. sweeploop1:
  975. /* search next marked object.
  976. enter address of the next marked object in *last_open_ptr . */
  977. if (p2==p2end) /* upper bound reached -> finished */
  978. goto sweepok1;
  979. {
  980. #ifdef TYPECODES
  981. var tint flags = mtypecode(((Varobject)p2)->GCself);
  982. /* save typeinfo (and flags for symbols) */
  983. #endif
  984. var uintM laenge = objsize((Varobject)p2); /* determine byte-length */
  985. if (!marked(p2)) { /* object unmarked? */
  986. p2 += laenge; goto sweeploop1; /* yes -> goto next object */
  987. }
  988. /* object marked
  989. Elimination of forward pointers: */
  990. #ifdef HAVE_SMALL_SSTRING
  991. #ifdef SPVW_PURE
  992. if (heapnr == sstring_type)
  993. #else
  994. #ifdef TYPECODES
  995. if ((flags & ~bit(garcol_bit_t)) == sstring_type)
  996. #else
  997. /* NB: No need to handle Rectype_[Imm_]S8string here. */
  998. if ((uintB)(record_type((Record)p2) - Rectype_S16string)
  999. <= Rectype_reallocstring - Rectype_S16string)
  1000. #endif
  1001. #endif
  1002. {
  1003. if (sstring_reallocatedp((Sstring)p2)) {
  1004. /* A forward pointer. */
  1005. gc_sweep1_sstring_forward(p2);
  1006. } else {
  1007. /* Possibly the target of a forward pointer. */
  1008. gc_sweep1_sstring_target(p2,p1);
  1009. }
  1010. }
  1011. else
  1012. #endif
  1013. #ifdef SPVW_PURE
  1014. if (heapnr == instance_type
  1015. || (heapnr == closure_type
  1016. && (closure_flags((Closure)p2) & closflags_instance_B)))
  1017. #else
  1018. #ifdef TYPECODES
  1019. if ((flags & ~bit(garcol_bit_t)) == instance_type
  1020. || ((flags & ~bit(garcol_bit_t)) == closure_type
  1021. && (closure_flags((Closure)p2) & closflags_instance_B)))
  1022. #else
  1023. if (record_type((Record)p2) == Rectype_Instance
  1024. || (record_type((Record)p2) == Rectype_Closure
  1025. && (closure_flags((Closure)p2) & closflags_instance_B)))
  1026. #endif
  1027. #endif
  1028. {
  1029. if (record_flags((Instance)p2) & instflags_forwarded_B) {
  1030. /* A forward pointer. */
  1031. gc_sweep1_instance_forward(p2);
  1032. } else {
  1033. /* Possibly the target of a forward pointer. */
  1034. gc_sweep1_instance_target(p2,p1);
  1035. }
  1036. }
  1037. else {
  1038. set_GCself(p2, flags,p1); /* enter new address, with old */
  1039. /* typeinfo (the mark bit is contained within) */
  1040. #ifndef TYPECODES
  1041. mark(p2);
  1042. #endif
  1043. }
  1044. *last_open_ptr = pointer_as_object(p2); /* store address */
  1045. p2 += laenge; /* source address for next object */
  1046. p1 += laenge; /* destination address for next object */
  1047. }
  1048. sweeploop2:
  1049. /* search next unmarked object. */
  1050. if (p2==p2end) /* upper bound reached -> finished */
  1051. goto sweepok2;
  1052. {
  1053. #ifdef TYPECODES
  1054. var tint flags = mtypecode(((Varobject)p2)->GCself);
  1055. /* save typeinfo (and flags for symbols) */
  1056. #endif
  1057. var uintM laenge = objsize((Varobject)p2); /* determine byte-length */
  1058. if (!marked(p2)) { /* object unmarked? */
  1059. last_open_ptr = (gcv_object_t*)p2; /* yes -> store the next pointer here */
  1060. p2 += laenge; goto sweeploop1; /* goto next object */
  1061. }
  1062. /* object marked
  1063. Elimination of forward pointers: */
  1064. #ifdef HAVE_SMALL_SSTRING
  1065. #ifdef SPVW_PURE
  1066. if (heapnr == sstring_type)
  1067. #else
  1068. #ifdef TYPECODES
  1069. if ((flags & ~bit(garcol_bit_t)) == sstring_type)
  1070. #else
  1071. /* NB: No need to handle Rectype_[Imm_]S8string here. */
  1072. if ((uintB)(record_type((Record)p2) - Rectype_S16string)
  1073. <= Rectype_reallocstring - Rectype_S16string)
  1074. #endif
  1075. #endif
  1076. {
  1077. if (sstring_reallocatedp((Sstring)p2)) {
  1078. /* A forward pointer. */
  1079. gc_sweep1_sstring_forward(p2);
  1080. } else {
  1081. /* Possibly the target of a forward pointer. */
  1082. gc_sweep1_sstring_target(p2,p1);
  1083. }
  1084. }
  1085. else
  1086. #endif
  1087. #ifdef SPVW_PURE
  1088. if (heapnr == instance_type
  1089. || (heapnr == closure_type
  1090. && (closure_flags((Closure)p2) & closflags_instance_B)))
  1091. #else
  1092. #ifdef TYPECODES
  1093. if ((flags & ~bit(garcol_bit_t)) == instance_type
  1094. || ((flags & ~bit(garcol_bit_t)) == closure_type
  1095. && (closure_flags((Closure)p2) & closflags_instance_B)))
  1096. #else
  1097. if (record_type((Record)p2) == Rectype_Instance
  1098. || (record_type((Record)p2) == Rectype_Closure
  1099. && (closure_flags((Closure)p2) & closflags_instance_B)))
  1100. #endif
  1101. #endif
  1102. {
  1103. if (record_flags((Instance)p2) & instflags_forwarded_B) {
  1104. /* A forward pointer. */
  1105. gc_sweep1_instance_forward(p2);
  1106. } else {
  1107. /* Possibly the target of a forward pointer. */
  1108. gc_sweep1_instance_target(p2,p1);
  1109. }
  1110. }
  1111. else {
  1112. set_GCself(p2, flags,p1); /* enter new address, with old */
  1113. /* typeinfo (the mark bit is contained within) */
  1114. #ifndef TYPECODES
  1115. mark(p2);
  1116. #endif
  1117. }
  1118. p2 += laenge; /* source address for next object */
  1119. p1 += laenge; /* destination address for next object */
  1120. goto sweeploop2;
  1121. }
  1122. sweepok1: { *last_open_ptr = pointer_as_object(p2); }
  1123. sweepok2: ;
  1124. #if defined(SPVW_PURE) || defined(GENERATIONAL_GC)
  1125. return p1;
  1126. #endif
  1127. }
  1128. /* update phase:
  1129. The entire LISP-memory is perused and old addresses are replaced
  1130. with new ones.
  1131. update of an object *objptr : */
  1132. #if !defined(MORRIS_GC)
  1133. #ifdef TYPECODES
  1134. #define update(objptr) \
  1135. { var tint type = mtypecode(*(gcv_object_t*)objptr); \
  1136. if (!gcinvariant_type_p(type)) { /* un-movable -> do nothing */ \
  1137. var object obj = *(gcv_object_t*)objptr; /* object */ \
  1138. if (!in_old_generation(obj,type,mem.heapnr_from_type[type])) \
  1139. /* older generation -> do nothing (object stayed there) */ \
  1140. if (marked(ThePointer(obj))) { /* marked? */ \
  1141. /* no -> do nothing (object stayed there) \
  1142. yes -> enter new address and typeinfobyte (incl. \
  1143. poss. symbol-binding-flag) */ \
  1144. var object newptr = \
  1145. type_untype_object(type,untype(*(gcv_object_t*)ThePointer(obj))); \
  1146. DEBUG_SPVW_ASSERT(is_valid_heap_object_address(as_oint(newptr)) \
  1147. || is_valid_stack_address(as_oint(newptr))); \
  1148. *(gcv_object_t*)objptr = newptr; \
  1149. } \
  1150. } \
  1151. }
  1152. #else
  1153. #ifdef GENERATIONAL_GC
  1154. #define update(objptr) \
  1155. { var object obj = *(gcv_object_t*)objptr; /* object */ \
  1156. if (!gcinvariant_object_p(obj)) /* un-movable -> do nothing */ \
  1157. if (!(consp(obj) ? in_old_generation(obj,,1) : in_old_generation(obj,,0))) \
  1158. /* older generation -> do nothing (object stayed there) */ \
  1159. if (marked(ThePointer(obj))) { /* marked? */ \
  1160. /* no -> do nothing (object stayed there) \
  1161. yes -> enter new address */ \
  1162. var object newptr = \
  1163. as_object((as_oint(obj) & nonimmediate_bias_mask) | (as_oint(*(gcv_object_t*)ThePointer(obj)) & ~wbit(garcol_bit_o))); \
  1164. DEBUG_SPVW_ASSERT((consp(obj) ? is_valid_cons_address(as_oint(newptr)) : is_valid_varobject_address(as_oint(newptr))) \
  1165. || is_valid_stack_address(as_oint(newptr))); \
  1166. *(gcv_object_t*)objptr = newptr; \
  1167. } \
  1168. }
  1169. #else
  1170. #define update(objptr) \
  1171. { var object obj = *(gcv_object_t*)objptr; /* object */ \
  1172. if (!gcinvariant_object_p(obj)) /* un-movable -> do nothing */ \
  1173. if (!in_old_generation(obj,,)) \
  1174. /* older generation -> do nothing (object stayed there) */ \
  1175. if (marked(ThePointer(obj))) { /* marked? */ \
  1176. /* no -> do nothing (object stayed there) \
  1177. yes -> enter new address */ \
  1178. var object newptr = \
  1179. as_object((as_oint(obj) & nonimmediate_bias_mask) | (as_oint(*(gcv_object_t*)ThePointer(obj)) & ~wbit(garcol_bit_o))); \
  1180. DEBUG_SPVW_ASSERT((consp(obj) ? is_valid_cons_address(as_oint(newptr)) : is_valid_varobject_address(as_oint(newptr))) \
  1181. || is_valid_stack_address(as_oint(newptr))); \
  1182. *(gcv_object_t*)objptr = newptr; \
  1183. } \
  1184. }
  1185. #endif
  1186. #endif
  1187. #else /* defined(MORRIS_GC) */
  1188. #if defined(SPVW_MIXED_BLOCKS)
  1189. #ifdef TYPECODES
  1190. #define update(objptr) \
  1191. { var tint type = mtypecode(*(gcv_object_t*)objptr); \
  1192. if (!gcinvariant_type_p(type)) /* un-movable -> do nothing */ \
  1193. switch (type) { \
  1194. default: { /* object of variable length */ \
  1195. var object obj = *(gcv_object_t*)objptr; /* object */ \
  1196. if (!in_old_generation(obj,type,0)) \
  1197. if (marked(ThePointer(obj))) { /* marked? */ \
  1198. var object newptr =

Large files files are truncated, but you can click here to view the full file