| 1 | /* Copyright (C) 2012,2016 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 | /* newObject (s, header, bytesRequested, allocInOldGen) |
| 11 | * |
| 12 | * Allocate a new object in the heap. |
| 13 | * bytesRequested includes the size of the header. |
| 14 | */ |
| 15 | pointer newObject (GC_state s, |
| 16 | GC_header header, |
| 17 | size_t bytesRequested, |
| 18 | bool allocInOldGen) { |
| 19 | pointer frontier; |
| 20 | pointer result; |
| 21 | |
| 22 | assert (isAligned (bytesRequested, s->alignment)); |
| 23 | assert (allocInOldGen |
| 24 | ? hasHeapBytesFree (s, bytesRequested, 0) |
| 25 | : hasHeapBytesFree (s, 0, bytesRequested)); |
| 26 | if (allocInOldGen) { |
| 27 | frontier = s->heap.start + s->heap.oldGenSize; |
| 28 | s->heap.oldGenSize += bytesRequested; |
| 29 | s->cumulativeStatistics.bytesAllocated += bytesRequested; |
| 30 | } else { |
| 31 | if (DEBUG_DETAILED) |
| 32 | fprintf (stderr, "frontier changed from "FMTPTR" to "FMTPTR"\n", |
| 33 | (uintptr_t)s->frontier, |
| 34 | (uintptr_t)(s->frontier + bytesRequested)); |
| 35 | frontier = s->frontier; |
| 36 | s->frontier += bytesRequested; |
| 37 | } |
| 38 | GC_profileAllocInc (s, bytesRequested); |
| 39 | *((GC_header*)frontier) = header; |
| 40 | result = frontier + GC_HEADER_SIZE; |
| 41 | assert (isAligned ((size_t)result, s->alignment)); |
| 42 | if (DEBUG) |
| 43 | fprintf (stderr, FMTPTR " = newObject ("FMTHDR", %"PRIuMAX", %s)\n", |
| 44 | (uintptr_t)result, |
| 45 | header, |
| 46 | (uintmax_t)bytesRequested, |
| 47 | boolToString (allocInOldGen)); |
| 48 | return result; |
| 49 | } |
| 50 | |
| 51 | GC_stack newStack (GC_state s, |
| 52 | size_t reserved, |
| 53 | bool allocInOldGen) { |
| 54 | GC_stack stack; |
| 55 | |
| 56 | assert (isStackReservedAligned (s, reserved)); |
| 57 | if (reserved > s->cumulativeStatistics.maxStackSize) |
| 58 | s->cumulativeStatistics.maxStackSize = reserved; |
| 59 | stack = (GC_stack)(newObject (s, GC_STACK_HEADER, |
| 60 | sizeofStackWithMetaData (s, reserved), |
| 61 | allocInOldGen)); |
| 62 | stack->reserved = reserved; |
| 63 | stack->used = 0; |
| 64 | if (DEBUG_STACKS) |
| 65 | fprintf (stderr, FMTPTR " = newStack (%"PRIuMAX")\n", |
| 66 | (uintptr_t)stack, |
| 67 | (uintmax_t)reserved); |
| 68 | return stack; |
| 69 | } |
| 70 | |
| 71 | GC_thread newThread (GC_state s, size_t reserved) { |
| 72 | GC_stack stack; |
| 73 | GC_thread thread; |
| 74 | pointer res; |
| 75 | |
| 76 | assert (isStackReservedAligned (s, reserved)); |
| 77 | ensureHasHeapBytesFree (s, 0, sizeofStackWithMetaData (s, reserved) + sizeofThread (s)); |
| 78 | stack = newStack (s, reserved, FALSE); |
| 79 | res = newObject (s, GC_THREAD_HEADER, |
| 80 | sizeofThread (s), |
| 81 | FALSE); |
| 82 | thread = (GC_thread)(res + offsetofThread (s)); |
| 83 | thread->bytesNeeded = 0; |
| 84 | thread->exnStack = BOGUS_EXN_STACK; |
| 85 | thread->stack = pointerToObjptr((pointer)stack, s->heap.start); |
| 86 | if (DEBUG_THREADS) |
| 87 | fprintf (stderr, FMTPTR" = newThreadOfSize (%"PRIuMAX")\n", |
| 88 | (uintptr_t)thread, (uintmax_t)reserved);; |
| 89 | return thread; |
| 90 | } |
| 91 | |
| 92 | static inline void setFrontier (GC_state s, pointer p, |
| 93 | ARG_USED_FOR_ASSERT size_t bytes) { |
| 94 | p = alignFrontier (s, p); |
| 95 | assert ((size_t)(p - s->frontier) <= bytes); |
| 96 | GC_profileAllocInc (s, (size_t)(p - s->frontier)); |
| 97 | s->cumulativeStatistics.bytesAllocated += (size_t)(p - s->frontier); |
| 98 | s->frontier = p; |
| 99 | assert (s->frontier <= s->limitPlusSlop); |
| 100 | } |