blob: 3792f861d4418ebe34bf975770751375bc6a9239 [file] [log] [blame]
Chris Lattner77ac7ba2004-05-23 21:25:45 +00001/*===-- semispace.c - Simple semi-space copying garbage collector ---------===*\
2|*
3|* The LLVM Compiler Infrastructure
4|*
5|* This file was developed by the LLVM research group and is distributed under
6|* the University of Illinois Open Source License. See LICENSE.TXT for details.
7|*
8|*===----------------------------------------------------------------------===*|
9|*
10|* This garbage collector is an extremely simple copying collector. It splits
11|* the managed region of memory into two pieces: the current space to allocate
12|* from, and the copying space. When the portion being allocated from fills up,
13|* a garbage collection cycle happens, which copies all live blocks to the other
14|* half of the managed space.
15|*
16\*===----------------------------------------------------------------------===*/
17
18#include "../GCInterface.h"
19#include <stdio.h>
20#include <stdlib.h>
21
22/* FIXME: This should be in a code-generator specific library!
23 */
24typedef struct GCRoot {
25 void **RootPtr;
26 void *Meta;
27} GCRoot;
28
29typedef struct GCRoots {
30 struct GCRoots *Next;
31 unsigned NumRoots;
32 GCRoot RootRecords[];
33} GCRoots;
34GCRoots *llvm_gc_root_chain;
35
36static void llvm_cg_walk_gcroots(void (*FP)(void **Root, void *Meta)) {
37 GCRoots *R = llvm_gc_root_chain;
38 for (; R; R = R->Next) {
39 unsigned i, e;
40 for (i = 0, e = R->NumRoots; i != e; ++i)
41 FP(R->RootRecords[i].RootPtr, R->RootRecords[i].Meta);
42 }
43}
44/* END FIXME! */
45
46
47
48/* We use no read/write barriers */
49void *llvm_gc_read(void **P) { return *P; }
50void llvm_gc_write(void *V, void **P) { *P = V; }
51
52
53/* AllocPtr - This points to the next byte that is available for allocation.
54 */
55static char *AllocPtr;
56
57/* AllocEnd - This points to the first byte not available for allocation. When
58 * AllocPtr passes this, we have run out of space.
59 */
60static char *AllocEnd;
61
62void llvm_gc_initialize() {
63 AllocPtr = calloc(1, 1000);
64 AllocEnd = AllocPtr + 1000;
65}
66
67/* We always want to inline the fast path, but never want to inline the slow
68 * path.
69 */
70void *llvm_gc_allocate(unsigned Size) __attribute__((always_inline));
71static void* llvm_gc_alloc_slow(unsigned Size) __attribute__((noinline));
72
73void *llvm_gc_allocate(unsigned Size) {
74 char *OldAP = AllocPtr;
75 char *NewEnd = OldAP+Size;
76 if (NewEnd > AllocEnd)
77 return llvm_gc_alloc_slow(Size);
78 AllocPtr = NewEnd;
79 return OldAP;
80}
81
82static void* llvm_gc_alloc_slow(unsigned Size) {
83 llvm_gc_collect();
84 return llvm_gc_allocate(Size);
85}
86
87
88static void process_root(void **Root, void *Meta) {
89 printf("process_root[0x%X] = 0x%X\n", Root, *Root);
90}
91
92void llvm_gc_collect() {
93 printf("Garbage collecting!!\n");
94 llvm_cg_walk_gcroots(process_root);
95 abort();
96
97 /* TODO: Iterate through roots. */
98}