Import Upstream version 20180207
[hcoop/debian/mlton.git] / runtime / gc / array-allocate.c
... / ...
CommitLineData
1/* Copyright (C) 2016 Matthew Fluet.
2 * Copyright (C) 1999-2007 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
10pointer GC_arrayAllocate (GC_state s,
11 size_t ensureBytesFree,
12 GC_arrayLength numElements,
13 GC_header header) {
14 size_t arraySize, arraySizeAligned;
15 size_t bytesPerElement;
16 uint16_t bytesNonObjptrs;
17 uint16_t numObjptrs;
18 pointer frontier;
19 pointer last;
20 pointer result;
21
22 splitHeader(s, header, NULL, NULL, &bytesNonObjptrs, &numObjptrs);
23 if (DEBUG)
24 fprintf (stderr, "GC_arrayAllocate (%"PRIuMAX", "FMTARRLEN", "FMTHDR")\n",
25 (uintmax_t)ensureBytesFree, numElements, header);
26 bytesPerElement = bytesNonObjptrs + (numObjptrs * OBJPTR_SIZE);
27 /* Check for overflow when computing arraySize.
28 */
29 if (bytesPerElement > 0 and numElements > (SIZE_MAX / bytesPerElement)) {
30 goto doOverflow;
31 }
32 arraySize = bytesPerElement * numElements;
33 if (arraySize > SIZE_MAX - GC_ARRAY_METADATA_SIZE) {
34 goto doOverflow;
35 }
36 arraySize += GC_ARRAY_METADATA_SIZE;
37 arraySizeAligned = align (arraySize, s->alignment);
38 if (arraySizeAligned < arraySize) {
39 goto doOverflow;
40 }
41 if (DEBUG_ARRAY)
42 fprintf (stderr,
43 "Array with "FMTARRLEN" elts of size %"PRIuMAX" and total size %s and total aligned size %s. "
44 "Ensure %s bytes free.\n",
45 numElements, (uintmax_t)bytesPerElement,
46 uintmaxToCommaString(arraySize),
47 uintmaxToCommaString(arraySizeAligned),
48 uintmaxToCommaString(ensureBytesFree));
49 if (arraySizeAligned >= s->controls.oldGenArraySize) {
50 if (not hasHeapBytesFree (s, arraySizeAligned, ensureBytesFree)) {
51 enter (s);
52 performGC (s, arraySizeAligned, ensureBytesFree, FALSE, TRUE);
53 leave (s);
54 }
55 frontier = s->heap.start + s->heap.oldGenSize;
56 s->heap.oldGenSize += arraySizeAligned;
57 s->cumulativeStatistics.bytesAllocated += arraySizeAligned;
58 } else {
59 size_t bytesRequested;
60 pointer newFrontier;
61
62 bytesRequested = arraySizeAligned + ensureBytesFree;
63 if (not hasHeapBytesFree (s, 0, bytesRequested)) {
64 enter (s);
65 performGC (s, 0, bytesRequested, FALSE, TRUE);
66 leave (s);
67 }
68 frontier = s->frontier;
69 newFrontier = frontier + arraySizeAligned;
70 assert (isFrontierAligned (s, newFrontier));
71 s->frontier = newFrontier;
72 }
73 last = frontier + arraySize;
74 *((GC_arrayCounter*)(frontier)) = 0;
75 frontier = frontier + GC_ARRAY_COUNTER_SIZE;
76 *((GC_arrayLength*)(frontier)) = numElements;
77 frontier = frontier + GC_ARRAY_LENGTH_SIZE;
78 *((GC_header*)(frontier)) = header;
79 frontier = frontier + GC_HEADER_SIZE;
80 result = frontier;
81 assert (isAligned ((size_t)result, s->alignment));
82 /* Initialize all pointers with BOGUS_OBJPTR. */
83 if (1 <= numObjptrs and 0 < numElements) {
84 pointer p;
85
86 if (0 == bytesNonObjptrs)
87 for (p = frontier; p < last; p += OBJPTR_SIZE)
88 *((objptr*)p) = BOGUS_OBJPTR;
89 else {
90 /* Array with a mix of pointers and non-pointers. */
91 size_t bytesObjptrs;
92
93 bytesObjptrs = numObjptrs * OBJPTR_SIZE;
94
95 for (p = frontier; p < last; ) {
96 pointer next;
97
98 p += bytesNonObjptrs;
99 next = p + bytesObjptrs;
100 assert (next <= last);
101 for ( ; p < next; p += OBJPTR_SIZE)
102 *((objptr*)p) = BOGUS_OBJPTR;
103 }
104 }
105 }
106 GC_profileAllocInc (s, arraySizeAligned);
107 if (DEBUG_ARRAY) {
108 fprintf (stderr, "GC_arrayAllocate done. result = "FMTPTR" frontier = "FMTPTR"\n",
109 (uintptr_t)result, (uintptr_t)s->frontier);
110 displayGCState (s, stderr);
111 }
112 assert (ensureBytesFree <= (size_t)(s->limitPlusSlop - s->frontier));
113 /* Unfortunately, the invariant isn't quite true here, because
114 * unless we did the GC, we never set s->currentThread->stack->used
115 * to reflect what the mutator did with stackTop.
116 */
117 return result;
118
119doOverflow:
120 die ("Out of memory. Unable to allocate array with "FMTARRLEN" elements and elements of size %"PRIuMAX" bytes.",
121 numElements, (uintmax_t)bytesPerElement);
122}