From caac00e5ff33202b6ab9d9f4a931c00b321110d7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 19 Jun 2007 20:28:31 -0600 Subject: [PATCH] start rough sketch of GC code in heap.cpp --- src/heap.cpp | 215 +++++++++++++++++++++++++++++++++++++++++ src/heap.h | 3 +- src/type-generator.cpp | 4 +- src/vm.h | 16 +++ 4 files changed, 235 insertions(+), 3 deletions(-) create mode 100644 src/heap.cpp create mode 100644 src/vm.h diff --git a/src/heap.cpp b/src/heap.cpp new file mode 100644 index 0000000000..e74cd9195d --- /dev/null +++ b/src/heap.cpp @@ -0,0 +1,215 @@ +#include "heap.h" +#include "system.h" + +using namespace vm; + +namespace { + +class Context { + public: +}; + +void +collect(Context* c, void** p) +{ + object original = *p; + object parent = 0; + + bool needsVisit; + *p = update(c, p, &needsVisit); + + if (not needsVisit) return; + + visit: { + object copy = follow(original); + + class Walker : public Heap::Walker { + public: + Walker(Context* c, object copy, uintptr_t* bitset): + c(c), + copy(copy), + bitset(bitset), + first(0), + last(0), + visits(0), + total(0) + { } + + virtual bool visit(unsigned offset) { + bool needsVisit; + object childCopy = update + (c, &cast(copy, offset * sizeof(void*)), &needsVisit); + + ++ total; + + if (total == 3) { + bitsetInit(bitset); + } + + if (needsVisit) { + ++ visits; + + if (visits == 1) { + first = offset; + } + + if (total >= 3) { + bitsetClear(bitset, last, offset); + last = offset; + + bitsetSet(bitset, offset, true); + } + } else { + cast(copy, offset * sizeof(void*)) = childCopy; + } + + return true; + } + + Context* c; + object copy; + uintptr_t* bitset; + unsigned first; + unsigned last; + unsigned visits; + unsigned total; + } walker(c, copy, bitset(original)); + + c->client->walk(copy, &walker); + + if (walker.visits) { + // descend + if (walker.visits > 1) { + ::parent(original) = parent; + + parent = original; + } + + original = cast(copy, walker.first * sizeof(void*)); + cast(copy, walker.first * sizeof(void*)) = follow(original); + goto visit; + } else { + // ascend + original = parent; + } + } + + if (original) { + object copy = follow(original); + + class Walker : public Heap::Walker { + public: + Walker(uintptr_t* bitset): + bitset(bitset), + next(0), + total(0) + { } + + virtual bool visit(unsigned offset) { + switch (++ total) { + case 1: + return true; + + case 2: + next = offset; + return true; + + case 3: + next = bitsetNext(bitset); + return false; + + default: + abort(c); + } + } + + uintptr_t* bitset; + unsigned next; + unsigned total; + } walker(c, copy, bitset(original)); + + assert(c, walker.total > 1); + + if (walker.total == 3 and bitsetHasMore(bitset(original))) { + parent = original; + } else { + parent = ::parent(original); + } + + original = cast(copy, walker.next * sizeof(void*)); + cast(copy, walker.next * sizeof(void*)) = follow(original); + } else { + return; + } +} + +void +collect2(Context* c) +{ + if (c->mode == MinorCollection and c->gen2.position()) { + unsigned start = 0; + unsigned end = start + c->gen2.position(); + bool dirty; + collect(m, &(c->map), start, end, &dirty, false); + } else if (c->mode == Gen2Collection) { + unsigned ng2Position = c->nextGen2.position(); + collect(m, &(c->nextGen1), c->nextGen1.position()); + collect(m, &(c->nextGen2), ng2Position); + } + + class Visitor : public Heap::Visitor { + public: + Visitor(Context* c): c(c) { } + + virtual void visit(void** p) { + collect(c, p); + } + } v(c); + + c->iterator->iterate(&v); +} + +void +collect1(Context* c) +{ + switch (c->mode) { + case MinorCollection: { + initNextGen1(c); + + collect2(c); + + if (c->mode == OverflowCollection) { + c->mode = Gen2Collection; + collect2(c); + + c->gen2.replaceWith(&(c->nextGen2)); + } + + c->gen1.replaceWith(&(c->nextGen1)); + } break; + + case MajorCollection: { + initNextGen1(c); + initNextGen2(c); + + c->map.clear(); + + collect2(c); + + c->gen1.replaceWith(&(c->nextGen1)); + c->gen2.replaceWith(&(c->nextGen2)); + } break; + } +} + +} // namespace + +Heap* +makeHeap(System* system) +{ + + + HeapImp* h = static_cast(system->allocate(sizeof(HeapImp))); + init(h, system); + return h; +} diff --git a/src/heap.h b/src/heap.h index a6e1f96718..c63815ff15 100644 --- a/src/heap.h +++ b/src/heap.h @@ -25,7 +25,8 @@ class Heap { virtual ~Heap() { } virtual void collect(CollectionType type, Iterator* it) = 0; virtual bool needsMark(void** p) = 0; - virtual void mark(void** p); + virtual void mark(void** p) = 0; + virtual void dispose() = 0; }; } // namespace vm diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 59f616435f..b32b189f48 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1489,7 +1489,7 @@ typeCount(Object* declarations) void writeInitializations(Output* out, Object* declarations) { - out->write(" t->vm->types = makeArray(t, "); + out->write("t->vm->types = makeArray(t, "); out->write(typeCount(declarations)); out->write(");\n\n"); @@ -1500,7 +1500,7 @@ writeInitializations(Output* out, Object* declarations) } } - out->write(" set(t, objectClass(t->vm->types), "); + out->write("set(t, objectClass(t->vm->types), "); out->write("arrayBody(t, t->vm->types, Machine::ArrayType));\n"); } diff --git a/src/vm.h b/src/vm.h new file mode 100644 index 0000000000..5c7afcee9d --- /dev/null +++ b/src/vm.h @@ -0,0 +1,16 @@ +#ifndef VM_H +#define VM_H + +#include "system.h" +#include "heap.h" +#include "class_finder.h" + +namespace vm { + +void +run(System* sys, Heap* heap, ClassFinder* classFinder, + const char* className, int argc, const char** argv); + +} + +#endif//VM_H