1 /* Copyright (C) 2012,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 void displayStack (__attribute__ ((unused
)) GC_state s
,
14 "\t\treserved = %"PRIuMAX
"\n"
15 "\t\tused = %"PRIuMAX
"\n",
16 (uintmax_t)stack
->reserved
,
17 (uintmax_t)stack
->used
);
22 bool isStackEmpty (GC_stack stack
) {
23 return 0 == stack
->used
;
26 bool isStackReservedAligned (GC_state s
, size_t reserved
) {
27 return isAligned (GC_STACK_METADATA_SIZE
+ sizeof (struct GC_stack
) + reserved
,
32 /* sizeofStackSlop returns the amount of "slop" space needed between
33 * the top of the stack and the end of the stack space.
35 size_t sizeofStackSlop (GC_state s
) {
36 return (size_t)(2 * s
->maxFrameSize
);
40 /* Pointer to the bottommost word in use on the stack. */
41 pointer
getStackBottom (ARG_USED_FOR_ASSERT GC_state s
, GC_stack stack
) {
44 res
= ((pointer
)stack
) + sizeof (struct GC_stack
);
45 assert (isAligned ((size_t)res
, s
->alignment
));
49 /* Pointer to the topmost word in use on the stack. */
50 pointer
getStackTop (GC_state s
, GC_stack stack
) {
53 res
= getStackBottom (s
, stack
) + stack
->used
;
54 assert (isAligned ((size_t)res
, s
->alignment
));
58 /* Pointer to the end of stack. */
59 pointer
getStackLimitPlusSlop (GC_state s
, GC_stack stack
) {
62 res
= getStackBottom (s
, stack
) + stack
->reserved
;
63 // assert (isAligned ((size_t)res, s->alignment));
67 /* The maximum value which is valid for stackTop. */
68 pointer
getStackLimit (GC_state s
, GC_stack stack
) {
71 res
= getStackLimitPlusSlop (s
, stack
) - sizeofStackSlop (s
);
72 // assert (isAligned ((size_t)res, s->alignment));
76 GC_frameIndex
getCachedStackTopFrameIndex (GC_state s
) {
80 getFrameIndexFromReturnAddress
81 (s
, *((GC_returnAddress
*)(s
->stackTop
- GC_RETURNADDRESS_SIZE
)));
85 GC_frameIndex
getStackTopFrameIndex (GC_state s
, GC_stack stack
) {
89 getFrameIndexFromReturnAddress
90 (s
, *((GC_returnAddress
*)(getStackTop (s
, stack
) - GC_RETURNADDRESS_SIZE
)));
94 GC_frameLayout
getStackTopFrameLayout (GC_state s
, GC_stack stack
) {
95 GC_frameLayout layout
;
97 layout
= getFrameLayoutFromFrameIndex (s
, getStackTopFrameIndex (s
, stack
));
101 uint16_t getStackTopFrameSize (GC_state s
, GC_stack stack
) {
102 GC_frameLayout layout
;
104 assert (not (isStackEmpty (stack
)));
105 layout
= getStackTopFrameLayout (s
, stack
);
110 size_t alignStackReserved (GC_state s
, size_t reserved
) {
113 res
= alignWithExtra (s
, reserved
, GC_STACK_METADATA_SIZE
+ sizeof (struct GC_stack
));
115 fprintf (stderr
, "%"PRIuMAX
" = alignStackReserved (%"PRIuMAX
")\n",
116 (uintmax_t)res
, (uintmax_t)reserved
);
117 assert (isStackReservedAligned (s
, res
));
121 size_t sizeofStackWithMetaData (ARG_USED_FOR_ASSERT GC_state s
, size_t reserved
) {
124 assert (isStackReservedAligned (s
, reserved
));
125 res
= GC_STACK_METADATA_SIZE
+ sizeof (struct GC_stack
) + reserved
;
127 fprintf (stderr
, "%"PRIuMAX
" = sizeofStackWithMetaData (%"PRIuMAX
")\n",
128 (uintmax_t)res
, (uintmax_t)reserved
);
129 assert (isAligned (res
, s
->alignment
));
133 size_t sizeofStackInitialReserved (GC_state s
) {
136 res
= alignStackReserved(s
, sizeofStackSlop (s
));
140 size_t sizeofStackMinimumReserved (GC_state s
, GC_stack stack
) {
143 res
= alignStackReserved (s
,
145 + sizeofStackSlop (s
)
146 - getStackTopFrameSize (s
, stack
));
150 size_t sizeofStackGrowReserved (GC_state s
, GC_stack stack
) {
152 size_t reservedGrow
, reservedMin
, reservedNew
;
153 const size_t RESERVED_MAX
= (SIZE_MAX
>> 2);
155 assert (isStackReservedAligned (s
, stack
->reserved
));
156 reservedD
= (double)(stack
->reserved
);
157 double reservedGrowD
=
158 (double)s
->controls
.ratios
.stackCurrentGrow
* reservedD
;
160 reservedGrowD
> (double)RESERVED_MAX
162 : (size_t)reservedGrowD
;
163 reservedMin
= sizeofStackMinimumReserved (s
, stack
);
166 (s
, max (reservedGrow
, reservedMin
));
167 assert (isStackReservedAligned (s
, reservedNew
));
171 size_t sizeofStackShrinkReserved (GC_state s
, GC_stack stack
, bool current
) {
172 double usedD
, reservedD
;
173 size_t reservedMax
, reservedShrink
, reservedMin
, reservedNew
;
174 const size_t RESERVED_MAX
= (SIZE_MAX
>> 2);
176 assert (isStackReservedAligned (s
, stack
->reserved
));
177 usedD
= (double)(stack
->used
);
178 reservedD
= (double)(stack
->reserved
);
180 /* Shrink current stacks. */
181 double reservedMaxD
=
182 (double)(s
->controls
.ratios
.stackCurrentMaxReserved
) * usedD
;
184 reservedMaxD
> (double)RESERVED_MAX
186 : (size_t)reservedMaxD
;
187 double reservedPermitD
=
188 (double)(s
->controls
.ratios
.stackCurrentPermitReserved
) * usedD
;
189 size_t reservedPermit
=
190 reservedPermitD
> (double)RESERVED_MAX
192 : (size_t)reservedPermitD
;
194 (stack
->reserved
<= reservedPermit
)
196 : (size_t)((double)(s
->controls
.ratios
.stackCurrentShrink
) * reservedD
);
197 reservedMin
= sizeofStackMinimumReserved (s
, stack
);
199 /* Shrink paused stacks. */
200 double reservedMaxD
=
201 (double)(s
->controls
.ratios
.stackMaxReserved
) * usedD
;
203 reservedMaxD
> (double)RESERVED_MAX
205 : (size_t)reservedMaxD
;
207 (size_t)((double)s
->controls
.ratios
.stackShrink
* reservedD
);
208 reservedMin
= stack
->used
;
212 (s
, max(min(reservedMax
,reservedShrink
),reservedMin
));
213 /* It's possible that reservedNew > stack->reserved for the current
214 * stack if the stack invariant is violated. In that case, we want
215 * to leave the stack alone, because some other part of the gc will
216 * grow the stack. We cannot do any growing here because we may run
219 assert (current
or reservedNew
<= stack
->reserved
);
220 reservedNew
= min (stack
->reserved
, reservedNew
);
221 assert (isStackReservedAligned (s
, reservedNew
));
225 void copyStack (GC_state s
, GC_stack from
, GC_stack to
) {
226 pointer fromBottom
, toBottom
;
228 fromBottom
= getStackBottom (s
, from
);
229 toBottom
= getStackBottom (s
, to
);
230 assert (from
->used
<= to
->reserved
);
231 to
->used
= from
->used
;
233 fprintf (stderr
, "stackCopy from "FMTPTR
" to "FMTPTR
" of length %"PRIuMAX
"\n",
234 (uintptr_t)fromBottom
,
236 (uintmax_t)from
->used
);
237 GC_memcpy (fromBottom
, toBottom
, from
->used
);