Chris Lattner | 77ac7ba | 2004-05-23 21:25:45 +0000 | [diff] [blame] | 1 | /*===-- 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 | */ |
| 24 | typedef struct GCRoot { |
| 25 | void **RootPtr; |
| 26 | void *Meta; |
| 27 | } GCRoot; |
| 28 | |
| 29 | typedef struct GCRoots { |
| 30 | struct GCRoots *Next; |
| 31 | unsigned NumRoots; |
| 32 | GCRoot RootRecords[]; |
| 33 | } GCRoots; |
| 34 | GCRoots *llvm_gc_root_chain; |
| 35 | |
| 36 | static 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 */ |
| 49 | void *llvm_gc_read(void **P) { return *P; } |
| 50 | void 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 | */ |
| 55 | static 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 | */ |
| 60 | static char *AllocEnd; |
| 61 | |
| 62 | void 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 | */ |
| 70 | void *llvm_gc_allocate(unsigned Size) __attribute__((always_inline)); |
| 71 | static void* llvm_gc_alloc_slow(unsigned Size) __attribute__((noinline)); |
| 72 | |
| 73 | void *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 | |
| 82 | static void* llvm_gc_alloc_slow(unsigned Size) { |
| 83 | llvm_gc_collect(); |
| 84 | return llvm_gc_allocate(Size); |
| 85 | } |
| 86 | |
| 87 | |
| 88 | static void process_root(void **Root, void *Meta) { |
Alkis Evlogimenos | 86f2382 | 2004-05-23 23:02:35 +0000 | [diff] [blame] | 89 | printf("process_root[0x%X] = 0x%X\n", (unsigned) Root, (unsigned) *Root); |
Chris Lattner | 77ac7ba | 2004-05-23 21:25:45 +0000 | [diff] [blame] | 90 | } |
| 91 | |
| 92 | void llvm_gc_collect() { |
| 93 | printf("Garbage collecting!!\n"); |
| 94 | llvm_cg_walk_gcroots(process_root); |
| 95 | abort(); |
| 96 | |
| 97 | /* TODO: Iterate through roots. */ |
| 98 | } |