Skip to content

Commit

Permalink
Start of the GC implementation.
Browse files Browse the repository at this point in the history
Implemented a function to mark the values on the stack.
Implemented allocated, a value in the vm object that keeps track of the memory used.
Implemented a linked list of all the Values which are pointers.
  • Loading branch information
Marco Rudilosso authored and Maaarcocr committed Sep 19, 2017
1 parent e75ce12 commit 411f601
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 9 deletions.
57 changes: 57 additions & 0 deletions vm/interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "interp.h"
#include "packages.h"
#include <math.h>
#include <unordered_set>

/// Opcode enumeration
enum Opcode : uint16_t
Expand Down Expand Up @@ -226,6 +227,62 @@ uint8_t* instrPtr = nullptr;
/// Cache of all possible one-character string values
Value charStrings[256];

void markValues(Value* root)
{
// size_t i = 0;
std::vector<refptr> toMark = { (refptr)root };
while (!toMark.empty())
{
// i++;
refptr ptr = toMark.back();
Tag tag = *(Tag*)ptr;
Value root = Value(ptr, tag);
toMark.pop_back();
if (root.isPointer())
{
// If this node was previously visited, skip it
if (root.isMarked())
continue;
// Mark the node as visited
root.setMark();
}
if (root.getTag() == TAG_OBJECT)
{
Object objRoot = (Object)(root);
for (auto itr = ObjFieldItr(objRoot); itr.valid(); itr.next())
{
auto fieldName = itr.get();
Value field = objRoot.getField(fieldName);
Tag tag = field.getTag();
if (tag == TAG_ARRAY || tag == TAG_OBJECT || tag == TAG_STRING)
toMark.push_back((refptr)field);
}
}
else if (root.getTag() == TAG_ARRAY)
{
Array arrRoot = (Array)(root);
auto len = arrRoot.length();
for(size_t i = 0; i < len; i++)
{
Value field = arrRoot.getElem(i);
Tag tag = field.getTag();
if (tag == TAG_ARRAY || tag == TAG_OBJECT || tag == TAG_STRING)
toMark.push_back((refptr)field);
}
}
}
// std::cout << i << std::endl;
}

void mark() {
for(auto ptr = stackPtr; ptr < stackBase; ptr++)
{
Tag tag = ptr->getTag();
if (tag == TAG_ARRAY || tag == TAG_OBJECT || tag == TAG_STRING)
markValues(ptr);
}
}

/// Write a value to the code heap
template <typename T> void writeCode(T val)
{
Expand Down
2 changes: 2 additions & 0 deletions vm/interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ typedef std::vector<Value> ValueVec;
/// Initialize the interpreter
void initInterp();

void mark();

/// Call a function exported by a package
Value callExportFn(
Object pkg,
Expand Down
34 changes: 31 additions & 3 deletions vm/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <cstring>
#include <iostream>
#include "runtime.h"
#include "interp.h"

/// Undefined value constant
/// Note: zeroed memory is automatically undefined
Expand Down Expand Up @@ -70,6 +71,28 @@ bool Value::isPointer() const
}
}

bool Value::isMarked() const
{
assert (isPointer());
refptr obj = this->word.ptr;
auto header = *(uint64_t*)obj;
return (header & HEADER_MSK_MARK) == HEADER_MSK_MARK;
}
void Value::setMark()
{
assert (isPointer());
refptr obj = this->word.ptr;
auto header = *(uint64_t*)obj;
*(uint64_t*)(obj) = header | HEADER_MSK_MARK;
}
void Value::unsetMark()
{
assert (isPointer());
refptr obj = this->word.ptr;
auto header = *(uint64_t*)obj;
*(uint64_t*)(obj) = header & (~HEADER_MSK_MARK);
}

Value::operator std::string () const
{
assert (isString());
Expand All @@ -88,10 +111,15 @@ Value VM::alloc(uint32_t size, Tag tag)
{
// FIXME: use an alloc pool of some kind
auto ptr = (refptr)calloc(1, size);

// Set the tag in the object header
// if (allocated >= limit)
// {
// // std::cout << "allocated: " << allocated << std::endl;
// mark();
// limit = allocated * 2;
// }
//Set the tag in the object header
*(Tag*)ptr = tag;

allocated += (size_t)size;
// Wrap the pointer in a tagged value
return Value(ptr, tag);
}
Expand Down
19 changes: 13 additions & 6 deletions vm/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ const size_t HEADER_SIZE = sizeof(intptr_t);
const size_t HEADER_IDX_NEXT = 15;
const size_t HEADER_MSK_NEXT = 1 << HEADER_IDX_NEXT;

const size_t HEADER_IDX_MARK = 31;
const size_t HEADER_MSK_MARK = 1 << HEADER_IDX_MARK;

/// Offset of the next pointer
const size_t OBJ_OF_NEXT = HEADER_SIZE;

Expand Down Expand Up @@ -64,7 +67,6 @@ class Value
Tag tag;

public:

static const Value ZERO;
static const Value ONE;
static const Value TWO;
Expand All @@ -77,7 +79,6 @@ class Value
Value(refptr p, Tag t) : Value(Word(p), t) {}
Value(Word w, Tag t) : word(w), tag(t) {};
~Value() {}

// Static constructors. These are needed because of type ambiguity.
static Value int32(int32_t v) { return Value(Word((int64_t)v), TAG_INT32); }
static Value float32(float v) { return Value(Word(v), TAG_FLOAT32); }
Expand All @@ -92,6 +93,10 @@ class Value

Word getWord() const { return word; }
Tag getTag() const { return tag; }
bool isMarked() const;
void setMark();
void unsetMark();


bool isPointer() const;

Expand Down Expand Up @@ -142,7 +147,9 @@ class VM
private:

// TODO: total memory size allocated

size_t allocated;
size_t limit = 30000;
Value* head;
// TODO: dynamically grow pools?

// TODO: pools for sizes up to 32 (words)
Expand All @@ -152,11 +159,11 @@ class VM
public:

VM();

size_t length; // TODO: get rid of this;
/// Allocate a block of memory on the heap
Value alloc(uint32_t size, Tag tag);

size_t allocated() const;
void setHead(Value* value) { head = value; }
Value* getHead() const { return head; }
};

/**
Expand Down

0 comments on commit 411f601

Please sign in to comment.