PageRenderTime 57ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/src/runtime/major_gc.c

https://github.com/bluegnu/mosml
C | 771 lines | 675 code | 45 blank | 51 comment | 384 complexity | 55d3c6771b0ae74ba1fe9bf6257df524 MD5 | raw file
Possible License(s): GPL-2.0
  1. #include <stdlib.h>
  2. #include <stdint.h>
  3. #include "config.h"
  4. #include "debugger.h"
  5. #include "fail.h"
  6. #include "freelist.h"
  7. #include "gc.h"
  8. #include "gc_ctrl.h"
  9. #include "globals.h"
  10. #include "major_gc.h"
  11. #include "misc.h"
  12. #include "mlvalues.h"
  13. #include "roots.h"
  14. #ifdef macintosh
  15. #include <Memory.h>
  16. #endif
  17. #include "runtime.h"
  18. #ifdef ANSI
  19. #include <limits.h>
  20. #else
  21. #ifdef SIXTYFOUR
  22. #define LONG_MAX 0x7FFFFFFFFFFFFFFF
  23. #else
  24. #define LONG_MAX 0x7FFFFFFF
  25. #endif
  26. #endif
  27. int percent_free;
  28. long major_heap_increment;
  29. char *heap_start, *heap_end;
  30. char *page_table;
  31. asize_t page_table_size;
  32. char *gc_sweep_hp;
  33. int gc_phase;
  34. typedef struct {
  35. intptr_t low, high;
  36. } p_table_entry;
  37. static p_table_entry *p_table;
  38. static size_t p_table_total_size;
  39. static size_t p_table_current_size;
  40. void p_table_init(size_t initial) {
  41. p_table = malloc(initial*sizeof(p_table_entry));
  42. if(p_table == NULL)
  43. fatal_error ("No room for allocating page table\n");
  44. p_table_total_size = initial;
  45. p_table_current_size = 0;
  46. }
  47. #define RawPage(p) (((intptr_t) (p)) >> Page_log)
  48. char p_table_in_heap_simple(addr a) {
  49. int i;
  50. intptr_t p = RawPage(a);
  51. for(i = 0; i < p_table_current_size; i++) {
  52. //printf("p: %u low: %u high: %u\n", p, p_table[i].low, p_table[i].high);
  53. if(p_table[i].low <= p && p < p_table[i].high) {
  54. return In_heap;
  55. }
  56. }
  57. return Not_in_heap;
  58. }
  59. char p_table_in_heap_16(addr a) {
  60. intptr_t p = RawPage(a);
  61. int i = 0;
  62. while(i + 15 < p_table_current_size) {
  63. if( (p_table[i].low <= p && p < p_table[i].high)
  64. || (p_table[i + 1].low <= p && p < p_table[i + 1].high)
  65. || (p_table[i + 2].low <= p && p < p_table[i + 2].high)
  66. || (p_table[i + 3].low <= p && p < p_table[i + 3].high)
  67. || (p_table[i + 4].low <= p && p < p_table[i + 4].high)
  68. || (p_table[i + 5].low <= p && p < p_table[i + 5].high)
  69. || (p_table[i + 6].low <= p && p < p_table[i + 6].high)
  70. || (p_table[i + 7].low <= p && p < p_table[i + 7].high)
  71. || (p_table[i + 8].low <= p && p < p_table[i + 8].high)
  72. || (p_table[i + 9].low <= p && p < p_table[i + 9].high)
  73. || (p_table[i + 10].low <= p && p < p_table[i + 10].high)
  74. || (p_table[i + 11].low <= p && p < p_table[i + 11].high)
  75. || (p_table[i + 12].low <= p && p < p_table[i + 12].high)
  76. || (p_table[i + 13].low <= p && p < p_table[i + 13].high)
  77. || (p_table[i + 14].low <= p && p < p_table[i + 14].high)
  78. || (p_table[i + 15].low <= p && p < p_table[i + 15].high)
  79. ) return In_heap;
  80. i += 16;
  81. }
  82. switch(p_table_current_size - i) {
  83. case 15:
  84. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  85. i++;
  86. case 14:
  87. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  88. i++;
  89. case 13:
  90. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  91. i++;
  92. case 12:
  93. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  94. i++;
  95. case 11:
  96. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  97. i++;
  98. case 10:
  99. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  100. i++;
  101. case 9:
  102. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  103. i++;
  104. case 8:
  105. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  106. i++;
  107. case 7:
  108. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  109. i++;
  110. case 6:
  111. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  112. i++;
  113. case 5:
  114. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  115. i++;
  116. case 4:
  117. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  118. i++;
  119. case 3:
  120. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  121. i++;
  122. case 2:
  123. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  124. i++;
  125. case 1:
  126. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  127. i++;
  128. default: return Not_in_heap;
  129. }
  130. }
  131. char p_table_in_heap(addr a) {
  132. intptr_t p = RawPage(a);
  133. int i = 0;
  134. while(i + 63 < p_table_current_size) {
  135. if( (p_table[i].low <= p && p < p_table[i].high)
  136. || (p_table[i + 1].low <= p && p < p_table[i + 1].high)
  137. || (p_table[i + 2].low <= p && p < p_table[i + 2].high)
  138. || (p_table[i + 3].low <= p && p < p_table[i + 3].high)
  139. || (p_table[i + 4].low <= p && p < p_table[i + 4].high)
  140. || (p_table[i + 5].low <= p && p < p_table[i + 5].high)
  141. || (p_table[i + 6].low <= p && p < p_table[i + 6].high)
  142. || (p_table[i + 7].low <= p && p < p_table[i + 7].high)
  143. || (p_table[i + 8].low <= p && p < p_table[i + 8].high)
  144. || (p_table[i + 9].low <= p && p < p_table[i + 9].high)
  145. || (p_table[i + 10].low <= p && p < p_table[i + 10].high)
  146. || (p_table[i + 11].low <= p && p < p_table[i + 11].high)
  147. || (p_table[i + 12].low <= p && p < p_table[i + 12].high)
  148. || (p_table[i + 13].low <= p && p < p_table[i + 13].high)
  149. || (p_table[i + 14].low <= p && p < p_table[i + 14].high)
  150. || (p_table[i + 15].low <= p && p < p_table[i + 15].high)
  151. || (p_table[i + 16].low <= p && p < p_table[i + 16].high)
  152. || (p_table[i + 17].low <= p && p < p_table[i + 17].high)
  153. || (p_table[i + 18].low <= p && p < p_table[i + 18].high)
  154. || (p_table[i + 19].low <= p && p < p_table[i + 19].high)
  155. || (p_table[i + 20].low <= p && p < p_table[i + 20].high)
  156. || (p_table[i + 21].low <= p && p < p_table[i + 21].high)
  157. || (p_table[i + 22].low <= p && p < p_table[i + 22].high)
  158. || (p_table[i + 23].low <= p && p < p_table[i + 23].high)
  159. || (p_table[i + 24].low <= p && p < p_table[i + 24].high)
  160. || (p_table[i + 25].low <= p && p < p_table[i + 25].high)
  161. || (p_table[i + 26].low <= p && p < p_table[i + 26].high)
  162. || (p_table[i + 27].low <= p && p < p_table[i + 27].high)
  163. || (p_table[i + 28].low <= p && p < p_table[i + 28].high)
  164. || (p_table[i + 29].low <= p && p < p_table[i + 29].high)
  165. || (p_table[i + 30].low <= p && p < p_table[i + 30].high)
  166. || (p_table[i + 31].low <= p && p < p_table[i + 31].high)
  167. || (p_table[i + 32].low <= p && p < p_table[i + 32].high)
  168. || (p_table[i + 33].low <= p && p < p_table[i + 33].high)
  169. || (p_table[i + 34].low <= p && p < p_table[i + 34].high)
  170. || (p_table[i + 35].low <= p && p < p_table[i + 35].high)
  171. || (p_table[i + 36].low <= p && p < p_table[i + 36].high)
  172. || (p_table[i + 37].low <= p && p < p_table[i + 37].high)
  173. || (p_table[i + 38].low <= p && p < p_table[i + 38].high)
  174. || (p_table[i + 39].low <= p && p < p_table[i + 39].high)
  175. || (p_table[i + 40].low <= p && p < p_table[i + 40].high)
  176. || (p_table[i + 41].low <= p && p < p_table[i + 41].high)
  177. || (p_table[i + 42].low <= p && p < p_table[i + 42].high)
  178. || (p_table[i + 43].low <= p && p < p_table[i + 43].high)
  179. || (p_table[i + 44].low <= p && p < p_table[i + 44].high)
  180. || (p_table[i + 45].low <= p && p < p_table[i + 45].high)
  181. || (p_table[i + 46].low <= p && p < p_table[i + 46].high)
  182. || (p_table[i + 47].low <= p && p < p_table[i + 47].high)
  183. || (p_table[i + 48].low <= p && p < p_table[i + 48].high)
  184. || (p_table[i + 49].low <= p && p < p_table[i + 49].high)
  185. || (p_table[i + 50].low <= p && p < p_table[i + 50].high)
  186. || (p_table[i + 51].low <= p && p < p_table[i + 51].high)
  187. || (p_table[i + 52].low <= p && p < p_table[i + 52].high)
  188. || (p_table[i + 53].low <= p && p < p_table[i + 53].high)
  189. || (p_table[i + 54].low <= p && p < p_table[i + 54].high)
  190. || (p_table[i + 55].low <= p && p < p_table[i + 55].high)
  191. || (p_table[i + 56].low <= p && p < p_table[i + 56].high)
  192. || (p_table[i + 57].low <= p && p < p_table[i + 57].high)
  193. || (p_table[i + 58].low <= p && p < p_table[i + 58].high)
  194. || (p_table[i + 59].low <= p && p < p_table[i + 59].high)
  195. || (p_table[i + 60].low <= p && p < p_table[i + 60].high)
  196. || (p_table[i + 61].low <= p && p < p_table[i + 61].high)
  197. || (p_table[i + 62].low <= p && p < p_table[i + 62].high)
  198. || (p_table[i + 63].low <= p && p < p_table[i + 63].high)
  199. ) return In_heap;
  200. i += 64;
  201. }
  202. switch(p_table_current_size - i) {
  203. case 63:
  204. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  205. i++;
  206. case 62:
  207. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  208. i++;
  209. case 61:
  210. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  211. i++;
  212. case 60:
  213. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  214. i++;
  215. case 59:
  216. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  217. i++;
  218. case 58:
  219. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  220. i++;
  221. case 57:
  222. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  223. i++;
  224. case 56:
  225. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  226. i++;
  227. case 55:
  228. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  229. i++;
  230. case 54:
  231. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  232. i++;
  233. case 53:
  234. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  235. i++;
  236. case 52:
  237. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  238. i++;
  239. case 51:
  240. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  241. i++;
  242. case 50:
  243. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  244. i++;
  245. case 49:
  246. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  247. i++;
  248. case 48:
  249. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  250. i++;
  251. case 47:
  252. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  253. i++;
  254. case 46:
  255. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  256. i++;
  257. case 45:
  258. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  259. i++;
  260. case 44:
  261. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  262. i++;
  263. case 43:
  264. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  265. i++;
  266. case 42:
  267. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  268. i++;
  269. case 41:
  270. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  271. i++;
  272. case 40:
  273. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  274. i++;
  275. case 39:
  276. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  277. i++;
  278. case 38:
  279. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  280. i++;
  281. case 37:
  282. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  283. i++;
  284. case 36:
  285. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  286. i++;
  287. case 35:
  288. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  289. i++;
  290. case 34:
  291. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  292. i++;
  293. case 33:
  294. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  295. i++;
  296. case 32:
  297. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  298. i++;
  299. case 31:
  300. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  301. i++;
  302. case 30:
  303. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  304. i++;
  305. case 29:
  306. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  307. i++;
  308. case 28:
  309. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  310. i++;
  311. case 27:
  312. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  313. i++;
  314. case 26:
  315. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  316. i++;
  317. case 25:
  318. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  319. i++;
  320. case 24:
  321. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  322. i++;
  323. case 23:
  324. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  325. i++;
  326. case 22:
  327. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  328. i++;
  329. case 21:
  330. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  331. i++;
  332. case 20:
  333. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  334. i++;
  335. case 19:
  336. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  337. i++;
  338. case 18:
  339. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  340. i++;
  341. case 17:
  342. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  343. i++;
  344. case 16:
  345. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  346. i++;
  347. case 15:
  348. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  349. i++;
  350. case 14:
  351. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  352. i++;
  353. case 13:
  354. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  355. i++;
  356. case 12:
  357. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  358. i++;
  359. case 11:
  360. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  361. i++;
  362. case 10:
  363. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  364. i++;
  365. case 9:
  366. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  367. i++;
  368. case 8:
  369. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  370. i++;
  371. case 7:
  372. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  373. i++;
  374. case 6:
  375. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  376. i++;
  377. case 5:
  378. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  379. i++;
  380. case 4:
  381. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  382. i++;
  383. case 3:
  384. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  385. i++;
  386. case 2:
  387. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  388. i++;
  389. case 1:
  390. if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
  391. i++;
  392. default: return Not_in_heap;
  393. }
  394. }
  395. void p_table_update_size() {
  396. p_table_total_size *= 2;
  397. p_table = realloc(p_table, sizeof(p_table_entry)*p_table_total_size);
  398. if(p_table == NULL)
  399. fatal_error("No memory for page table");
  400. gc_message ("Growing p_table to %ld\n", p_table_total_size);
  401. }
  402. void p_table_add_pages(addr start, addr end) {
  403. intptr_t s, e;
  404. if(p_table_current_size == p_table_total_size)
  405. p_table_update_size();
  406. p_table[p_table_current_size].low = RawPage(start);
  407. p_table[p_table_current_size].high = RawPage(end);
  408. p_table_current_size++;
  409. }
  410. /* The mark phase will register pointers to live arrays of weak
  411. pointers in weak_arrays. Then the weak phase traverses each weak
  412. array and resets pointers to objects that will be deallocated by the
  413. sweep phase:
  414. */
  415. static value *weak_arrays;
  416. value *weak_arrays_cur, *weak_arrays_end;
  417. static asize_t weak_arrays_size;
  418. static value *gray_vals;
  419. value *gray_vals_cur, *gray_vals_end;
  420. static asize_t gray_vals_size;
  421. static int heap_is_pure; /* The heap is pure if the only gray objects
  422. below [markhp] are also in [gray_vals]. */
  423. unsigned long allocated_words;
  424. unsigned long extra_heap_memory;
  425. extern char *fl_merge; /* Defined in freelist.c. */
  426. static char *markhp, *chunk, *limit;
  427. static void realloc_gray_vals (void)
  428. {
  429. value *new;
  430. Assert (gray_vals_cur == gray_vals_end);
  431. if (gray_vals_size < stat_heap_size / 128){
  432. gc_message ("Growing gray_vals to %ldk\n",
  433. (long) gray_vals_size * sizeof (value) / 512);
  434. new = (value *) realloc ((char *) gray_vals,
  435. 2 * gray_vals_size * sizeof (value));
  436. if (new == NULL){
  437. gc_message ("No room for growing gray_vals\n", 0);
  438. gray_vals_cur = gray_vals;
  439. heap_is_pure = 0;
  440. }else{
  441. gray_vals = new;
  442. gray_vals_cur = gray_vals + gray_vals_size;
  443. gray_vals_size *= 2;
  444. gray_vals_end = gray_vals + gray_vals_size;
  445. }
  446. }else{
  447. gray_vals_cur = gray_vals + gray_vals_size / 2;
  448. heap_is_pure = 0;
  449. }
  450. }
  451. static void realloc_weak_arrays (void)
  452. {
  453. value *new;
  454. Assert (weak_arrays_cur == weak_arrays_end);
  455. gc_message ("Growing weak_arrays to %ld\n",
  456. (long) weak_arrays_size * 2);
  457. new = (value *) realloc ((char *) weak_arrays,
  458. 2 * weak_arrays_size * sizeof (value));
  459. if (new == NULL){
  460. fatal_error ("Fatal error: cannot grow weak_arrays table.\n");
  461. }else{
  462. weak_arrays = new;
  463. weak_arrays_cur = weak_arrays + weak_arrays_size;
  464. weak_arrays_size *= 2;
  465. weak_arrays_end = weak_arrays + weak_arrays_size;
  466. }
  467. }
  468. void darken (value v)
  469. {
  470. if (Is_block (v) && Is_in_heap (v) && Is_white_val (v)){
  471. Hd_val (v) = Grayhd_hd (Hd_val (v));
  472. *gray_vals_cur++ = v;
  473. if (gray_vals_cur >= gray_vals_end) realloc_gray_vals ();
  474. }
  475. }
  476. static void darken_root (value *p, value v)
  477. {
  478. darken (v);
  479. }
  480. static void start_cycle (void)
  481. {
  482. Assert (gray_vals_cur == gray_vals);
  483. Assert (Is_white_val (global_data));
  484. darken (global_data);
  485. local_roots (darken_root);
  486. gc_phase = Phase_mark;
  487. markhp = NULL;
  488. }
  489. static void mark_slice (long work)
  490. {
  491. value v, child;
  492. mlsize_t i;
  493. while (work > 0){
  494. if (gray_vals_cur > gray_vals){
  495. v = *--gray_vals_cur;
  496. Assert (Is_gray_val (v));
  497. Hd_val (v) = Blackhd_hd (Hd_val (v));
  498. if (Tag_val (v) < No_scan_tag){
  499. for (i = Wosize_val (v); i > 0;){
  500. --i;
  501. child = Field (v, i);
  502. darken (child);
  503. }
  504. } else if (Tag_val(v) == Weak_tag) {
  505. *weak_arrays_cur++ = v;
  506. if (weak_arrays_cur >= weak_arrays_end) realloc_weak_arrays ();
  507. }
  508. work -= Whsize_val (v);
  509. }else if (markhp != NULL){
  510. if (markhp == limit){
  511. chunk = (((heap_chunk_head *) chunk) [-1]).next;
  512. if (chunk == NULL){
  513. markhp = NULL;
  514. }else{
  515. markhp = chunk;
  516. limit = chunk + (((heap_chunk_head *) chunk) [-1]).size;
  517. }
  518. }else{
  519. if (Is_gray_val (Val_hp (markhp))){
  520. Assert (gray_vals_cur == gray_vals);
  521. *gray_vals_cur++ = Val_hp (markhp);
  522. }
  523. markhp += Bhsize_hp (markhp);
  524. }
  525. }else if (!heap_is_pure){
  526. heap_is_pure = 1;
  527. chunk = heap_start;
  528. markhp = chunk;
  529. limit = chunk + (((heap_chunk_head *) chunk) [-1]).size;
  530. }else{
  531. /* Marking is done. */
  532. gc_sweep_hp = heap_start;
  533. fl_init_merge ();
  534. gc_phase = Phase_weak;
  535. chunk = heap_start;
  536. gc_sweep_hp = chunk;
  537. limit = chunk + (((heap_chunk_head *) chunk) [-1]).size;
  538. work = 0;
  539. }
  540. }
  541. }
  542. /* Reset weak pointers to objects that will be deallocated by the sweep phase
  543. */
  544. static void weak_phase()
  545. {
  546. value *c;
  547. for (c = weak_arrays; c < weak_arrays_cur; c++)
  548. {
  549. int i;
  550. value arr = *c;
  551. int len = Wosize_val(arr);
  552. for (i=0; i < len; i++)
  553. {
  554. value v = Field(arr, i);
  555. if (Is_block(v) && Is_in_heap(v) && Is_white_val(v))
  556. Field(arr, i) = (value)NULL;
  557. }
  558. }
  559. weak_arrays_cur = weak_arrays;
  560. gc_phase = Phase_sweep;
  561. }
  562. static void sweep_slice (long work)
  563. {
  564. char *hp;
  565. header_t hd;
  566. while (work > 0){
  567. if (gc_sweep_hp < limit){
  568. hp = gc_sweep_hp;
  569. hd = Hd_hp (hp);
  570. work -= Whsize_hd (hd);
  571. gc_sweep_hp += Bhsize_hd (hd);
  572. switch (Color_hd (hd)){
  573. case White:
  574. if (Tag_hd (hd) == Final_tag){
  575. Final_fun (Val_hp (hp)) (Val_hp (hp));
  576. }
  577. gc_sweep_hp = fl_merge_block (Bp_hp (hp));
  578. break;
  579. case Gray:
  580. Assert (0); /* Fall through to Black when not in debug mode. */
  581. case Black:
  582. Hd_hp (hp) = Whitehd_hd (hd);
  583. break;
  584. case Blue:
  585. /* Only the blocks of the free-list are blue. See [freelist.c]. */
  586. fl_merge = Bp_hp (hp);
  587. break;
  588. }
  589. Assert (gc_sweep_hp <= limit);
  590. }else{
  591. chunk = (((heap_chunk_head *) chunk) [-1]).next;
  592. if (chunk == NULL){
  593. /* Sweeping is done. Start the next cycle. */
  594. ++ stat_major_collections;
  595. work = 0;
  596. start_cycle ();
  597. }else{
  598. gc_sweep_hp = chunk;
  599. limit = chunk + (((heap_chunk_head *) chunk) [-1]).size;
  600. }
  601. }
  602. }
  603. }
  604. void major_collection_slice (void)
  605. {
  606. /* Free memory at the start of the GC cycle:
  607. FM = stat_heap_size * percent_free / 100 * 2/3
  608. Proportion of free memory consumed since the previous slice:
  609. PH = allocated_words / FM
  610. Proportion of extra-heap memory consumed since the previous slice:
  611. PE = extra_heap_memory / stat_heap_size
  612. Proportion of total work to do in this slice:
  613. P = PH + PE
  614. Amount of marking work for the GC cycle:
  615. MW = stat_heap_size * (100 - percent_free) / 100
  616. Amount of sweeping work for the GC cycle:
  617. SW = stat_heap_size
  618. Amount of marking work for this slice:
  619. MS = MW * 2 * P
  620. MS = 2 * (100 - percent_free)
  621. * (allocated_words * 3 / percent_free / 2
  622. + 100 * extra_heap_memory)
  623. Amount of sweeping work for this slice:
  624. SS = SW * 2 * P
  625. SS = 2 * 100
  626. * (allocated_words * 3 / percent_free / 2
  627. + 100 * extra_heap_memory)
  628. This slice will either mark MS words or sweep SS words.
  629. */
  630. #define Margin 100 /* Make it a little faster to be on the safe side. */
  631. if (gc_phase == Phase_mark){
  632. mark_slice (2 * (100 - percent_free)
  633. * (allocated_words * 3 / percent_free / 2
  634. + 100 * extra_heap_memory)
  635. + Margin);
  636. gc_message ("!", 0);
  637. }else if (gc_phase == Phase_weak){
  638. weak_phase();
  639. gc_message (".", 0);
  640. }else{
  641. Assert (gc_phase == Phase_sweep);
  642. sweep_slice (200 * (allocated_words * 3 / percent_free / 2
  643. + 100 * extra_heap_memory)
  644. + Margin);
  645. gc_message ("$", 0);
  646. }
  647. stat_major_words += allocated_words;
  648. allocated_words = 0;
  649. extra_heap_memory = 0;
  650. }
  651. /* The minor heap must be empty when this function is called. */
  652. void finish_major_cycle (void)
  653. {
  654. beg_gc_time();
  655. if (gc_phase == Phase_mark) mark_slice (LONG_MAX);
  656. if (gc_phase == Phase_weak) weak_phase();
  657. Assert (gc_phase == Phase_sweep);
  658. sweep_slice (LONG_MAX);
  659. stat_major_words += allocated_words;
  660. allocated_words = 0;
  661. end_gc_time();
  662. }
  663. asize_t round_heap_chunk_size (asize_t request)
  664. { Assert (major_heap_increment >= Heap_chunk_min);
  665. if (request < major_heap_increment){
  666. Assert (major_heap_increment % Page_size == 0);
  667. return major_heap_increment;
  668. }else if (request <= Heap_chunk_max){
  669. return ((request + Page_size - 1) >> Page_log) << Page_log;
  670. }else{
  671. raise_out_of_memory ();
  672. }
  673. return 0; /* Can't reach return */
  674. }
  675. void init_major_heap (asize_t heap_size)
  676. {
  677. asize_t i;
  678. stat_heap_size = round_heap_chunk_size (heap_size);
  679. Assert (stat_heap_size % Page_size == 0);
  680. heap_start = aligned_malloc (stat_heap_size + sizeof (heap_chunk_head),
  681. sizeof (heap_chunk_head));
  682. if (heap_start == NULL)
  683. fatal_error ("Fatal error: not enough memory for the initial heap.\n");
  684. heap_start += sizeof (heap_chunk_head);
  685. Assert ((unsigned long) heap_start % Page_size == 0);
  686. (((heap_chunk_head *) heap_start) [-1]).size = stat_heap_size;
  687. (((heap_chunk_head *) heap_start) [-1]).next = NULL;
  688. heap_end = heap_start + stat_heap_size;
  689. Assert ((unsigned long) heap_end % Page_size == 0);
  690. #ifdef SIXTEEN
  691. page_table_size = 640L * 1024L / Page_size + 1;
  692. #else
  693. page_table_size = 4 * stat_heap_size / Page_size;
  694. #endif
  695. /* page_table = (char *) malloc (page_table_size);
  696. if (page_table == NULL){
  697. fatal_error ("Fatal error: not enough memory for the initial heap.\n");
  698. }
  699. for (i = 0; i < page_table_size; i++){
  700. page_table [i] = Not_in_heap;
  701. }
  702. for (i = Page (heap_start); i < Page (heap_end); i++){
  703. page_table [i] = In_heap;
  704. }
  705. */
  706. // p_table_init(page_table_size);
  707. p_table_init(64);
  708. p_table_add_pages(heap_start, heap_end);
  709. Hd_hp (heap_start) = Make_header (Wosize_bhsize (stat_heap_size), 0, Blue);
  710. fl_init_merge ();
  711. fl_merge_block (Bp_hp (heap_start));
  712. /* We start the major GC in the marking phase, just after the roots have been
  713. darkened. (Since there are no roots, we don't have to darken anything.) */
  714. gc_phase = Phase_mark;
  715. weak_arrays_size = 1;
  716. weak_arrays = (value *) malloc (weak_arrays_size * sizeof (value));
  717. weak_arrays_cur = weak_arrays;
  718. weak_arrays_end = weak_arrays + weak_arrays_size;
  719. gray_vals_size = 2048;
  720. gray_vals = (value *) malloc (gray_vals_size * sizeof (value));
  721. gray_vals_cur = gray_vals;
  722. gray_vals_end = gray_vals + gray_vals_size;
  723. heap_is_pure = 1;
  724. allocated_words = 0;
  725. extra_heap_memory = 0;
  726. }