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.
6 * MLton is released under a BSD-style license.
7 * See the file MLton-LICENSE for details.
10 pointer
GC_arrayAllocate (GC_state s
,
11 size_t ensureBytesFree
,
12 GC_arrayLength numElements
,
14 size_t arraySize
, arraySizeAligned
;
15 size_t bytesPerElement
;
16 uint16_t bytesNonObjptrs
;
22 splitHeader(s
, header
, NULL
, NULL
, &bytesNonObjptrs
, &numObjptrs
);
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.
29 if (bytesPerElement
> 0 and numElements
> (SIZE_MAX
/ bytesPerElement
)) {
32 arraySize
= bytesPerElement
* numElements
;
33 if (arraySize
> SIZE_MAX
- GC_ARRAY_METADATA_SIZE
) {
36 arraySize
+= GC_ARRAY_METADATA_SIZE
;
37 arraySizeAligned
= align (arraySize
, s
->alignment
);
38 if (arraySizeAligned
< arraySize
) {
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
)) {
52 performGC (s
, arraySizeAligned
, ensureBytesFree
, FALSE
, TRUE
);
55 frontier
= s
->heap
.start
+ s
->heap
.oldGenSize
;
56 s
->heap
.oldGenSize
+= arraySizeAligned
;
57 s
->cumulativeStatistics
.bytesAllocated
+= arraySizeAligned
;
59 size_t bytesRequested
;
62 bytesRequested
= arraySizeAligned
+ ensureBytesFree
;
63 if (not hasHeapBytesFree (s
, 0, bytesRequested
)) {
65 performGC (s
, 0, bytesRequested
, FALSE
, TRUE
);
68 frontier
= s
->frontier
;
69 newFrontier
= frontier
+ arraySizeAligned
;
70 assert (isFrontierAligned (s
, newFrontier
));
71 s
->frontier
= newFrontier
;
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
;
81 assert (isAligned ((size_t)result
, s
->alignment
));
82 /* Initialize all pointers with BOGUS_OBJPTR. */
83 if (1 <= numObjptrs
and 0 < numElements
) {
86 if (0 == bytesNonObjptrs
)
87 for (p
= frontier
; p
< last
; p
+= OBJPTR_SIZE
)
88 *((objptr
*)p
) = BOGUS_OBJPTR
;
90 /* Array with a mix of pointers and non-pointers. */
93 bytesObjptrs
= numObjptrs
* OBJPTR_SIZE
;
95 for (p
= frontier
; p
< last
; ) {
99 next
= p
+ bytesObjptrs
;
100 assert (next
<= last
);
101 for ( ; p
< next
; p
+= OBJPTR_SIZE
)
102 *((objptr
*)p
) = BOGUS_OBJPTR
;
106 GC_profileAllocInc (s
, arraySizeAligned
);
108 fprintf (stderr
, "GC_arrayAllocate done. result = "FMTPTR
" frontier = "FMTPTR
"\n",
109 (uintptr_t)result
, (uintptr_t)s
->frontier
);
110 displayGCState (s
, stderr
);
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.
120 die ("Out of memory. Unable to allocate array with "FMTARRLEN
" elements and elements of size %"PRIuMAX
" bytes.",
121 numElements
, (uintmax_t)bytesPerElement
);