PageRenderTime 63ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/runtime/gc/init.c

https://github.com/gowthamk/mlton
C | 399 lines | 351 code | 17 blank | 31 comment | 146 complexity | 6860b65cf66a24a260dec735a385d221 MD5 | raw file
Possible License(s): LGPL-2.1, MIT
  1. /* Copyright (C) 2009,2012 Matthew Fluet.
  2. * Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
  3. * Jagannathan, and Stephen Weeks.
  4. * Copyright (C) 1997-2000 NEC Research Institute.
  5. *
  6. * MLton is released under a BSD-style license.
  7. * See the file MLton-LICENSE for details.
  8. */
  9. /* ---------------------------------------------------------------- */
  10. /* Initialization */
  11. /* ---------------------------------------------------------------- */
  12. static bool stringToBool (char *s) {
  13. if (0 == strcmp (s, "false"))
  14. return FALSE;
  15. if (0 == strcmp (s, "true"))
  16. return TRUE;
  17. die ("Invalid @MLton bool: %s.", s);
  18. }
  19. // From gdtoa/gdtoa.h.
  20. // Can't include the whole thing because it brings in too much junk.
  21. float gdtoa__strtof (const char *, char **);
  22. static float stringToFloat (char *s) {
  23. char *endptr;
  24. float f;
  25. f = gdtoa__strtof (s, &endptr);
  26. if (s == endptr)
  27. die ("Invalid @MLton float: %s.", s);
  28. return f;
  29. }
  30. static size_t stringToBytes (char *s) {
  31. double d;
  32. char *endptr;
  33. size_t factor;
  34. d = strtod (s, &endptr);
  35. if (s == endptr)
  36. goto bad;
  37. switch (*endptr++) {
  38. case 'g':
  39. case 'G':
  40. factor = 1024 * 1024 * 1024;
  41. break;
  42. case 'k':
  43. case 'K':
  44. factor = 1024;
  45. break;
  46. case 'm':
  47. case 'M':
  48. factor = 1024 * 1024;
  49. break;
  50. default:
  51. goto bad;
  52. }
  53. d *= factor;
  54. unless (*endptr == '\0'
  55. and 0.0 <= d
  56. and d <= (double)SIZE_MAX)
  57. goto bad;
  58. return (size_t)d;
  59. bad:
  60. die ("Invalid @MLton memory amount: %s.", s);
  61. }
  62. /* ---------------------------------------------------------------- */
  63. /* GC_init */
  64. /* ---------------------------------------------------------------- */
  65. int processAtMLton (GC_state s, int argc, char **argv,
  66. char **worldFile) {
  67. int i;
  68. i = 1;
  69. while (s->controls.mayProcessAtMLton
  70. and i < argc
  71. and (0 == strcmp (argv [i], "@MLton"))) {
  72. bool done;
  73. i++;
  74. done = FALSE;
  75. while (!done) {
  76. if (i == argc)
  77. die ("Missing -- at end of @MLton args.");
  78. else {
  79. char *arg;
  80. arg = argv[i];
  81. if (0 == strcmp (arg, "copy-generational-ratio")) {
  82. i++;
  83. if (i == argc)
  84. die ("@MLton copy-generational-ratio missing argument.");
  85. s->controls.ratios.copyGenerational = stringToFloat (argv[i++]);
  86. unless (1.0 < s->controls.ratios.copyGenerational)
  87. die ("@MLton copy-generational-ratio argument must be greater than 1.0.");
  88. } else if (0 == strcmp (arg, "copy-ratio")) {
  89. i++;
  90. if (i == argc)
  91. die ("@MLton copy-ratio missing argument.");
  92. s->controls.ratios.copy = stringToFloat (argv[i++]);
  93. unless (1.0 < s->controls.ratios.copy)
  94. die ("@MLton copy-ratio argument must be greater than 1.0.");
  95. } else if (0 == strcmp (arg, "fixed-heap")) {
  96. i++;
  97. if (i == argc)
  98. die ("@MLton fixed-heap missing argument.");
  99. s->controls.fixedHeap = align (stringToBytes (argv[i++]),
  100. 2 * s->sysvals.pageSize);
  101. } else if (0 == strcmp (arg, "gc-messages")) {
  102. i++;
  103. s->controls.messages = TRUE;
  104. } else if (0 == strcmp (arg, "gc-summary")) {
  105. i++;
  106. s->controls.summary = TRUE;
  107. } else if (0 == strcmp (arg, "grow-ratio")) {
  108. i++;
  109. if (i == argc)
  110. die ("@MLton grow-ratio missing argument.");
  111. s->controls.ratios.grow = stringToFloat (argv[i++]);
  112. unless (1.0 < s->controls.ratios.grow)
  113. die ("@MLton grow-ratio argument must be greater than 1.0.");
  114. } else if (0 == strcmp (arg, "hash-cons")) {
  115. i++;
  116. if (i == argc)
  117. die ("@MLton hash-cons missing argument.");
  118. s->controls.ratios.hashCons = stringToFloat (argv[i++]);
  119. unless (0.0 <= s->controls.ratios.hashCons
  120. and s->controls.ratios.hashCons <= 1.0)
  121. die ("@MLton hash-cons argument must be between 0.0 and 1.0.");
  122. } else if (0 == strcmp (arg, "live-ratio")) {
  123. i++;
  124. if (i == argc)
  125. die ("@MLton live-ratio missing argument.");
  126. s->controls.ratios.live = stringToFloat (argv[i++]);
  127. unless (1.0 < s->controls.ratios.live)
  128. die ("@MLton live-ratio argument must be greater than 1.0.");
  129. } else if (0 == strcmp (arg, "load-world")) {
  130. unless (s->controls.mayLoadWorld)
  131. die ("May not load world.");
  132. i++;
  133. s->amOriginal = FALSE;
  134. if (i == argc)
  135. die ("@MLton load-world missing argument.");
  136. *worldFile = argv[i++];
  137. } else if (0 == strcmp (arg, "mark-compact-generational-ratio")) {
  138. i++;
  139. if (i == argc)
  140. die ("@MLton mark-compact-generational-ratio missing argument.");
  141. s->controls.ratios.markCompactGenerational = stringToFloat (argv[i++]);
  142. unless (1.0 < s->controls.ratios.markCompactGenerational)
  143. die ("@MLton mark-compact-generational-ratio argument must be greater than 1.0.");
  144. } else if (0 == strcmp (arg, "mark-compact-ratio")) {
  145. i++;
  146. if (i == argc)
  147. die ("@MLton mark-compact-ratio missing argument.");
  148. s->controls.ratios.markCompact = stringToFloat (argv[i++]);
  149. unless (1.0 < s->controls.ratios.markCompact)
  150. die ("@MLton mark-compact-ratio argument must be greater than 1.0.");
  151. } else if (0 == strcmp (arg, "max-heap")) {
  152. i++;
  153. if (i == argc)
  154. die ("@MLton max-heap missing argument.");
  155. s->controls.maxHeap = align (stringToBytes (argv[i++]),
  156. 2 * s->sysvals.pageSize);
  157. } else if (0 == strcmp (arg, "may-page-heap")) {
  158. i++;
  159. if (i == argc)
  160. die ("@MLton may-page-heap missing argument.");
  161. s->controls.mayPageHeap = stringToBool (argv[i++]);
  162. } else if (0 == strcmp (arg, "no-load-world")) {
  163. i++;
  164. s->controls.mayLoadWorld = FALSE;
  165. } else if (0 == strcmp (arg, "nursery-ratio")) {
  166. i++;
  167. if (i == argc)
  168. die ("@MLton nursery-ratio missing argument.");
  169. s->controls.ratios.nursery = stringToFloat (argv[i++]);
  170. unless (1.0 < s->controls.ratios.nursery)
  171. die ("@MLton nursery-ratio argument must be greater than 1.0.");
  172. } else if (0 == strcmp (arg, "ram-slop")) {
  173. i++;
  174. if (i == argc)
  175. die ("@MLton ram-slop missing argument.");
  176. s->controls.ratios.ramSlop = stringToFloat (argv[i++]);
  177. } else if (0 == strcmp (arg, "show-sources")) {
  178. showSources (s);
  179. exit (0);
  180. } else if (0 == strcmp (arg, "stop")) {
  181. i++;
  182. s->controls.mayProcessAtMLton = FALSE;
  183. } else if (0 == strcmp (arg, "stack-current-grow-ratio")) {
  184. i++;
  185. if (i == argc)
  186. die ("@MLton stack-current-grow-ratio missing argument.");
  187. s->controls.ratios.stackCurrentGrow = stringToFloat (argv[i++]);
  188. unless (1.0 < s->controls.ratios.stackCurrentGrow)
  189. die ("@MLton stack-current-grow-ratio argument must greater than 1.0.");
  190. } else if (0 == strcmp (arg, "stack-current-max-reserved-ratio")) {
  191. i++;
  192. if (i == argc)
  193. die ("@MLton stack-current-max-reserved-ratio missing argument.");
  194. s->controls.ratios.stackCurrentMaxReserved = stringToFloat (argv[i++]);
  195. unless (1.0 < s->controls.ratios.stackCurrentMaxReserved)
  196. die ("@MLton stack-current-max-reserved-ratio argument must greater than 1.0.");
  197. } else if (0 == strcmp (arg, "stack-current-permit-reserved-ratio")) {
  198. i++;
  199. if (i == argc)
  200. die ("@MLton stack-current-permit-reserved-ratio missing argument.");
  201. s->controls.ratios.stackCurrentPermitReserved = stringToFloat (argv[i++]);
  202. unless (1.0 < s->controls.ratios.stackCurrentPermitReserved)
  203. die ("@MLton stack-current-permit-reserved-ratio argument must greater than 1.0.");
  204. } else if (0 == strcmp (arg, "stack-current-shrink-ratio")) {
  205. i++;
  206. if (i == argc)
  207. die ("@MLton stack-current-shrink-ratio missing argument.");
  208. s->controls.ratios.stackCurrentShrink = stringToFloat (argv[i++]);
  209. unless (0.0 <= s->controls.ratios.stackCurrentShrink
  210. and s->controls.ratios.stackCurrentShrink <= 1.0)
  211. die ("@MLton stack-current-shrink-ratio argument must be between 0.0 and 1.0.");
  212. } else if (0 == strcmp (arg, "stack-max-reserved-ratio")) {
  213. i++;
  214. if (i == argc)
  215. die ("@MLton stack-max-reserved-ratio missing argument.");
  216. s->controls.ratios.stackMaxReserved = stringToFloat (argv[i++]);
  217. unless (1.0 < s->controls.ratios.stackMaxReserved)
  218. die ("@MLton stack-max-reserved-ratio argument must greater than 1.0.");
  219. } else if (0 == strcmp (arg, "stack-shrink-ratio")) {
  220. i++;
  221. if (i == argc)
  222. die ("@MLton stack-shrink-ratio missing argument.");
  223. s->controls.ratios.stackShrink = stringToFloat (argv[i++]);
  224. unless (0.0 <= s->controls.ratios.stackShrink
  225. and s->controls.ratios.stackShrink <= 1.0)
  226. die ("@MLton stack-shrink-ratio argument must be between 0.0 and 1.0.");
  227. } else if (0 == strcmp (arg, "use-mmap")) {
  228. i++;
  229. if (i == argc)
  230. die ("@MLton use-mmap missing argument.");
  231. GC_setCygwinUseMmap (stringToBool (argv[i++]));
  232. } else if (0 == strcmp (arg, "--")) {
  233. i++;
  234. done = TRUE;
  235. } else if (i > 1)
  236. die ("Strange @MLton arg: %s", argv[i]);
  237. else done = TRUE;
  238. }
  239. }
  240. }
  241. return i;
  242. }
  243. int GC_init (GC_state s, int argc, char **argv) {
  244. char *worldFile;
  245. int res;
  246. assert (s->alignment >= GC_MODEL_MINALIGN);
  247. assert (isAligned (sizeof (struct GC_stack), s->alignment));
  248. // While the following asserts are manifestly true,
  249. // they check the asserts in sizeofThread and sizeofWeak.
  250. assert (sizeofThread (s) == sizeofThread (s));
  251. assert (sizeofWeak (s) == sizeofWeak (s));
  252. s->amInGC = TRUE;
  253. s->amOriginal = TRUE;
  254. s->atomicState = 0;
  255. s->callFromCHandlerThread = BOGUS_OBJPTR;
  256. s->controls.fixedHeap = 0;
  257. s->controls.maxHeap = 0;
  258. s->controls.mayLoadWorld = TRUE;
  259. s->controls.mayPageHeap = FALSE;
  260. s->controls.mayProcessAtMLton = TRUE;
  261. s->controls.messages = FALSE;
  262. s->controls.oldGenArraySize = 0x100000;
  263. s->controls.ratios.copy = 4.0f;
  264. s->controls.ratios.copyGenerational = 4.0f;
  265. s->controls.ratios.grow = 8.0f;
  266. s->controls.ratios.hashCons = 0.0f;
  267. s->controls.ratios.live = 8.0f;
  268. s->controls.ratios.markCompact = 1.04f;
  269. s->controls.ratios.markCompactGenerational = 8.0f;
  270. s->controls.ratios.nursery = 10.0f;
  271. s->controls.ratios.ramSlop = 0.5f;
  272. s->controls.ratios.stackCurrentGrow = 2.0f;
  273. s->controls.ratios.stackCurrentMaxReserved = 32.0f;
  274. s->controls.ratios.stackCurrentPermitReserved = 4.0f;
  275. s->controls.ratios.stackCurrentShrink = 0.5f;
  276. s->controls.ratios.stackMaxReserved = 8.0f;
  277. s->controls.ratios.stackShrink = 0.5f;
  278. s->controls.summary = FALSE;
  279. s->cumulativeStatistics.bytesAllocated = 0;
  280. s->cumulativeStatistics.bytesCopied = 0;
  281. s->cumulativeStatistics.bytesCopiedMinor = 0;
  282. s->cumulativeStatistics.bytesHashConsed = 0;
  283. s->cumulativeStatistics.bytesMarkCompacted = 0;
  284. s->cumulativeStatistics.bytesScannedMinor = 0;
  285. s->cumulativeStatistics.maxBytesLive = 0;
  286. s->cumulativeStatistics.maxHeapSize = 0;
  287. s->cumulativeStatistics.maxPauseTime = 0;
  288. s->cumulativeStatistics.maxStackSize = 0;
  289. s->cumulativeStatistics.numCardsMarked = 0;
  290. s->cumulativeStatistics.numCopyingGCs = 0;
  291. s->cumulativeStatistics.numHashConsGCs = 0;
  292. s->cumulativeStatistics.numMarkCompactGCs = 0;
  293. s->cumulativeStatistics.numMinorGCs = 0;
  294. rusageZero (&s->cumulativeStatistics.ru_gc);
  295. rusageZero (&s->cumulativeStatistics.ru_gcCopying);
  296. rusageZero (&s->cumulativeStatistics.ru_gcMarkCompact);
  297. rusageZero (&s->cumulativeStatistics.ru_gcMinor);
  298. s->currentThread = BOGUS_OBJPTR;
  299. s->hashConsDuringGC = FALSE;
  300. initHeap (s, &s->heap);
  301. s->lastMajorStatistics.bytesHashConsed = 0;
  302. s->lastMajorStatistics.bytesLive = 0;
  303. s->lastMajorStatistics.kind = GC_COPYING;
  304. s->lastMajorStatistics.numMinorGCs = 0;
  305. s->savedThread = BOGUS_OBJPTR;
  306. initHeap (s, &s->secondaryHeap);
  307. s->signalHandlerThread = BOGUS_OBJPTR;
  308. s->signalsInfo.amInSignalHandler = FALSE;
  309. s->signalsInfo.gcSignalHandled = FALSE;
  310. s->signalsInfo.gcSignalPending = FALSE;
  311. s->signalsInfo.signalIsPending = FALSE;
  312. sigemptyset (&s->signalsInfo.signalsHandled);
  313. sigemptyset (&s->signalsInfo.signalsPending);
  314. s->sysvals.pageSize = GC_pageSize ();
  315. s->sysvals.physMem = GC_physMem ();
  316. s->weaks = NULL;
  317. s->saveWorldStatus = true;
  318. initIntInf (s);
  319. initSignalStack (s);
  320. worldFile = NULL;
  321. unless (isAligned (s->sysvals.pageSize, CARD_SIZE))
  322. die ("Page size must be a multiple of card size.");
  323. processAtMLton (s, s->atMLtonsLength, s->atMLtons, &worldFile);
  324. res = processAtMLton (s, argc, argv, &worldFile);
  325. if (s->controls.fixedHeap > 0 and s->controls.maxHeap > 0)
  326. die ("Cannot use both fixed-heap and max-heap.");
  327. unless (s->controls.ratios.markCompact <= s->controls.ratios.copy
  328. and s->controls.ratios.copy <= s->controls.ratios.live)
  329. die ("Ratios must satisfy mark-compact-ratio <= copy-ratio <= live-ratio.");
  330. unless (s->controls.ratios.stackCurrentPermitReserved
  331. <= s->controls.ratios.stackCurrentMaxReserved)
  332. die ("Ratios must satisfy stack-current-permit-reserved <= stack-current-max-reserved.");
  333. /* We align s->sysvals.ram by s->sysvals.pageSize so that we can
  334. * test whether or not we we are using mark-compact by comparing
  335. * heap size to ram size. If we didn't round, the size might be
  336. * slightly off.
  337. */
  338. uintmax_t ram;
  339. ram = alignMax ((uintmax_t)(s->controls.ratios.ramSlop * (double)(s->sysvals.physMem)),
  340. (uintmax_t)(s->sysvals.pageSize));
  341. ram = min (ram, alignMaxDown((uintmax_t)SIZE_MAX, (uintmax_t)(s->sysvals.pageSize)));
  342. s->sysvals.ram = (size_t)ram;
  343. if (DEBUG or DEBUG_RESIZING or s->controls.messages)
  344. fprintf (stderr, "[GC: Found %s bytes of RAM; using %s bytes (%.1f%% of RAM).]\n",
  345. uintmaxToCommaString(s->sysvals.physMem),
  346. uintmaxToCommaString(s->sysvals.ram),
  347. 100.0 * ((double)ram / (double)(s->sysvals.physMem)));
  348. if (DEBUG_SOURCES or DEBUG_PROFILE) {
  349. uint32_t i;
  350. for (i = 0; i < s->sourceMaps.frameSourcesLength; i++) {
  351. uint32_t j;
  352. uint32_t *sourceSeq;
  353. fprintf (stderr, "%"PRIu32"\n", i);
  354. sourceSeq = s->sourceMaps.sourceSeqs[s->sourceMaps.frameSources[i]];
  355. for (j = 1; j <= sourceSeq[0]; j++)
  356. fprintf (stderr, "\t%s\n",
  357. s->sourceMaps.sourceNames[
  358. s->sourceMaps.sources[sourceSeq[j]].sourceNameIndex
  359. ]);
  360. }
  361. }
  362. /* Initialize profiling. This must occur after processing
  363. * command-line arguments, because those may just be doing a
  364. * show-sources, in which case we don't want to initialize the
  365. * atExit.
  366. */
  367. initProfiling (s);
  368. if (s->amOriginal) {
  369. initWorld (s);
  370. /* The mutator stack invariant doesn't hold,
  371. * because the mutator has yet to run.
  372. */
  373. assert (invariantForMutator (s, TRUE, FALSE));
  374. } else {
  375. loadWorldFromFileName (s, worldFile);
  376. if (s->profiling.isOn and s->profiling.stack)
  377. foreachStackFrame (s, enterFrameForProfiling);
  378. assert (invariantForMutator (s, TRUE, TRUE));
  379. }
  380. s->amInGC = FALSE;
  381. return res;
  382. }