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