File: stack.c

package info (click to toggle)
mlton 20130715-3
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 60,900 kB
  • ctags: 69,386
  • sloc: xml: 34,418; ansic: 17,399; lisp: 2,879; makefile: 1,605; sh: 1,254; pascal: 256; python: 143; asm: 97
file content (238 lines) | stat: -rw-r--r-- 7,267 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/* Copyright (C) 2012 Matthew Fluet.
 * Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
 *    Jagannathan, and Stephen Weeks.
 * Copyright (C) 1997-2000 NEC Research Institute.
 *
 * MLton is released under a BSD-style license.
 * See the file MLton-LICENSE for details.
 */

void displayStack (__attribute__ ((unused)) GC_state s,
                   GC_stack stack,
                   FILE *stream) {
  fprintf(stream,
          "\t\treserved = %"PRIuMAX"\n"
          "\t\tused = %"PRIuMAX"\n",
          (uintmax_t)stack->reserved,
          (uintmax_t)stack->used);
}


#if ASSERT
bool isStackEmpty (GC_stack stack) {
  return 0 == stack->used;
}

bool isStackReservedAligned (GC_state s, size_t reserved) {
  return isAligned (GC_STACK_HEADER_SIZE + sizeof (struct GC_stack) + reserved,
                    s->alignment);
}
#endif

/* sizeofStackSlop returns the amount of "slop" space needed between
 * the top of the stack and the end of the stack space.
 */
size_t sizeofStackSlop (GC_state s) {
  return (size_t)(2 * s->maxFrameSize);
}


/* Pointer to the bottommost word in use on the stack. */
pointer getStackBottom (ARG_USED_FOR_ASSERT GC_state s, GC_stack stack) {
  pointer res;

  res = ((pointer)stack) + sizeof (struct GC_stack);
  assert (isAligned ((size_t)res, s->alignment));
  return res;
}

/* Pointer to the topmost word in use on the stack. */
pointer getStackTop (GC_state s, GC_stack stack) {
  pointer res;

  res = getStackBottom (s, stack) + stack->used;
  assert (isAligned ((size_t)res, s->alignment));
  return res;
}

/* Pointer to the end of stack. */
pointer getStackLimitPlusSlop (GC_state s, GC_stack stack) {
  pointer res;

  res = getStackBottom (s, stack) + stack->reserved;
  // assert (isAligned ((size_t)res, s->alignment));
  return res;
}

/* The maximum value which is valid for stackTop. */
pointer getStackLimit (GC_state s, GC_stack stack) {
  pointer res;

  res  = getStackLimitPlusSlop (s, stack) - sizeofStackSlop (s);
  // assert (isAligned ((size_t)res, s->alignment));
  return res;
}

GC_frameIndex getCachedStackTopFrameIndex (GC_state s) {
  GC_frameIndex res;

  res =
    getFrameIndexFromReturnAddress
    (s, *((GC_returnAddress*)(s->stackTop - GC_RETURNADDRESS_SIZE)));
  return res;
}

GC_frameIndex getStackTopFrameIndex (GC_state s, GC_stack stack) {
  GC_frameIndex res;

  res =
    getFrameIndexFromReturnAddress
    (s, *((GC_returnAddress*)(getStackTop (s, stack) - GC_RETURNADDRESS_SIZE)));
  return res;
}

GC_frameLayout getStackTopFrameLayout (GC_state s, GC_stack stack) {
  GC_frameLayout layout;

  layout = getFrameLayoutFromFrameIndex (s, getStackTopFrameIndex (s, stack));
  return layout;
}

uint16_t getStackTopFrameSize (GC_state s, GC_stack stack) {
  GC_frameLayout layout;

  assert (not (isStackEmpty (stack)));
  layout = getStackTopFrameLayout (s, stack);
  return layout->size;
}


size_t alignStackReserved (GC_state s, size_t reserved) {
  size_t res;

  res = alignWithExtra (s, reserved, GC_STACK_HEADER_SIZE + sizeof (struct GC_stack));
  if (DEBUG_STACKS)
    fprintf (stderr, "%"PRIuMAX" = alignStackReserved (%"PRIuMAX")\n",
             (uintmax_t)res, (uintmax_t)reserved);
  assert (isStackReservedAligned (s, res));
  return res;
}

size_t sizeofStackWithHeader (ARG_USED_FOR_ASSERT GC_state s, size_t reserved) {
  size_t res;

  assert (isStackReservedAligned (s, reserved));
  res = GC_STACK_HEADER_SIZE + sizeof (struct GC_stack) + reserved;
  if (DEBUG_STACKS)
    fprintf (stderr, "%"PRIuMAX" = sizeofStackWithHeader (%"PRIuMAX")\n",
             (uintmax_t)res, (uintmax_t)reserved);
  assert (isAligned (res, s->alignment));
  return res;
}

size_t sizeofStackInitialReserved (GC_state s) {
  size_t res;

  res = alignStackReserved(s, sizeofStackSlop (s));
  return res;
}

size_t sizeofStackMinimumReserved (GC_state s, GC_stack stack) {
  size_t res;

  res = alignStackReserved (s, 
                            stack->used
                            + sizeofStackSlop (s)
                            - getStackTopFrameSize (s, stack));
  return res;
}

size_t sizeofStackGrowReserved (GC_state s, GC_stack stack) {
  double reservedD;
  size_t reservedGrow, reservedMin, reservedNew;
  const size_t RESERVED_MAX = (SIZE_MAX >> 2);

  assert (isStackReservedAligned (s, stack->reserved));
  reservedD = (double)(stack->reserved);
  double reservedGrowD =
    (double)s->controls.ratios.stackCurrentGrow * reservedD;
  reservedGrow =
    reservedGrowD > (double)RESERVED_MAX
    ? RESERVED_MAX
    : (size_t)reservedGrowD;
  reservedMin = sizeofStackMinimumReserved (s, stack);
  reservedNew =
    alignStackReserved
    (s, max (reservedGrow, reservedMin));
  assert (isStackReservedAligned (s, reservedNew));
  return reservedNew;
}

size_t sizeofStackShrinkReserved (GC_state s, GC_stack stack, bool current) {
  double usedD, reservedD;
  size_t reservedMax, reservedShrink, reservedMin, reservedNew;
  const size_t RESERVED_MAX = (SIZE_MAX >> 2);

  assert (isStackReservedAligned (s, stack->reserved));
  usedD = (double)(stack->used);
  reservedD = (double)(stack->reserved);
  if (current) {
    /* Shrink current stacks. */
    double reservedMaxD =
      (double)(s->controls.ratios.stackCurrentMaxReserved) * usedD;
    reservedMax =
      reservedMaxD > (double)RESERVED_MAX
      ? RESERVED_MAX
      : (size_t)reservedMaxD;
    double reservedPermitD =
      (double)(s->controls.ratios.stackCurrentPermitReserved) * usedD;
    size_t reservedPermit =
      reservedPermitD > (double)RESERVED_MAX
      ? RESERVED_MAX
      : (size_t)reservedPermitD;
    reservedShrink =
      (stack->reserved <= reservedPermit)
      ? stack->reserved
      : (size_t)((double)(s->controls.ratios.stackCurrentShrink) * reservedD);
    reservedMin = sizeofStackMinimumReserved (s, stack);
  } else {
    /* Shrink paused stacks. */
    double reservedMaxD =
      (double)(s->controls.ratios.stackMaxReserved) * usedD;
    reservedMax =
      reservedMaxD > (double)RESERVED_MAX
      ? RESERVED_MAX
      : (size_t)reservedMaxD;
    reservedShrink =
      (size_t)((double)s->controls.ratios.stackShrink * reservedD);
    reservedMin = stack->used;
  }
  reservedNew =
    alignStackReserved
    (s, max(min(reservedMax,reservedShrink),reservedMin));
  /* It's possible that reservedNew > stack->reserved for the current
   * stack if the stack invariant is violated.  In that case, we want
   * to leave the stack alone, because some other part of the gc will
   * grow the stack.  We cannot do any growing here because we may run
   * out of to space.
   */
  assert (current or reservedNew <= stack->reserved);
  reservedNew = min (stack->reserved, reservedNew);
  assert (isStackReservedAligned (s, reservedNew));
  return reservedNew;
}

void copyStack (GC_state s, GC_stack from, GC_stack to) {
  pointer fromBottom, toBottom;

  fromBottom = getStackBottom (s, from);
  toBottom = getStackBottom (s, to);
  assert (from->used <= to->reserved);
  to->used = from->used;
  if (DEBUG_STACKS)
    fprintf (stderr, "stackCopy from "FMTPTR" to "FMTPTR" of length %"PRIuMAX"\n",
             (uintptr_t)fromBottom,
             (uintptr_t)toBottom,
             (uintmax_t)from->used);
  GC_memcpy (fromBottom, toBottom, from->used);
}