Removed makefile + minor fixes
This commit is contained in:
parent
3e6e9da475
commit
15f3143599
5
Makefile
5
Makefile
|
@ -1,5 +0,0 @@
|
|||
repl:
|
||||
nim --hints:off --warnings:off r src/main.nim
|
||||
|
||||
pretty:
|
||||
nimpretty src/*.nim src/backend/*.nim src/frontend/*.nim src/frontend/meta/*.nim src/memory/*.nim src/util/*.nim
|
|
@ -57,7 +57,7 @@ type
|
|||
closures: seq[uint64] # Stores closure offsets
|
||||
envs: seq[uint64] # Stores variables that do not have stack semantics
|
||||
results: seq[uint64] # Stores function's results (return values)
|
||||
gc: PeonGC
|
||||
gc: PeonGC # Our memory manager
|
||||
ObjectKind* = enum
|
||||
## A tag for heap-allocated
|
||||
## peon objects
|
||||
|
@ -77,7 +77,10 @@ type
|
|||
discard # TODO
|
||||
PeonGC* = ref object
|
||||
## A simple Mark&Sweep collector
|
||||
## to manage peon's heap space
|
||||
## to manage peon's heap space.
|
||||
## All heap allocation goes through
|
||||
## this system and is not handled
|
||||
## manually by the VM
|
||||
vm: PeonVM
|
||||
bytesAllocated: tuple[total, current: int]
|
||||
nextGC: int
|
||||
|
@ -155,7 +158,7 @@ template free*(self: PeonGC, kind: typedesc, p: pointer): untyped =
|
|||
|
||||
proc allocate*(self: PeonGC, kind: ObjectKind, size: typedesc, count: int): ptr HeapObject {.inline.} =
|
||||
## Allocates aobject on the heap
|
||||
result = cast[ptr HeapObject](self.reallocate(nil, 0, sizeof(HeapObject) * 1))
|
||||
result = cast[ptr HeapObject](self.reallocate(nil, 0, sizeof(HeapObject)))
|
||||
result.marked = false
|
||||
self.bytesAllocated.total += sizeof(result)
|
||||
self.bytesAllocated.current += sizeof(result)
|
||||
|
@ -182,7 +185,8 @@ proc markRoots(self: PeonGC): seq[ptr HeapObject] =
|
|||
## Marks root objects *not* to be
|
||||
## collected by the GC and returns
|
||||
## their addresses
|
||||
|
||||
when debugGC:
|
||||
echo "DEBUG - GC: Starting mark phase"
|
||||
# Unlike what bob does in his book,
|
||||
# we keep track of objects in a different
|
||||
# way due to how the whole thing is designed.
|
||||
|
@ -204,9 +208,7 @@ proc markRoots(self: PeonGC): seq[ptr HeapObject] =
|
|||
# we allocated and that would cause a memory leak, but
|
||||
# with a 64-bit address-space it probably hardly matters,
|
||||
# so I guess this is a mostly-precise Mark&Sweep collector
|
||||
when debugGC:
|
||||
echo "DEBUG - GC: Starting mark phase"
|
||||
var live = initHashSet[uint64]()
|
||||
var live = initHashSet[uint64](self.pointers.len())
|
||||
for obj in self.vm.calls:
|
||||
if obj in self.pointers:
|
||||
live.incl(obj)
|
||||
|
@ -223,7 +225,7 @@ proc markRoots(self: PeonGC): seq[ptr HeapObject] =
|
|||
obj = cast[ptr HeapObject](p)
|
||||
if obj.mark():
|
||||
when debugGC:
|
||||
echo &"DEBUG - GC: Marking object: {obj[]}"
|
||||
echo &"DEBUG - GC: Marked object: {obj[]}"
|
||||
result.add(obj)
|
||||
when debugGC:
|
||||
echo "DEBUG - GC: Mark phase complete"
|
||||
|
@ -277,21 +279,21 @@ proc sweep(self: PeonGC) =
|
|||
## nim disallows changing the
|
||||
## size of a sequence during
|
||||
## iteration
|
||||
|
||||
when debugGC:
|
||||
echo "DEBUG - GC: Beginning sweeping phase"
|
||||
var j = -1
|
||||
var idx = 0
|
||||
var count = 0
|
||||
when debugGC:
|
||||
var count = 0
|
||||
while j < self.objects.high():
|
||||
inc(j)
|
||||
if self.objects[j].marked:
|
||||
# Object is marked: don't touch it,
|
||||
# but reset its mark so that it doesn't
|
||||
# stay alive forever
|
||||
self.objects[j].marked = false
|
||||
when debugGC:
|
||||
echo &"DEBUG - GC: Unmarking object: {self.objects[j][]}"
|
||||
self.objects[j].marked = false
|
||||
inc(idx)
|
||||
else:
|
||||
# Object is unmarked: its memory is
|
||||
|
@ -299,7 +301,8 @@ proc sweep(self: PeonGC) =
|
|||
self.free(self.objects[idx])
|
||||
self.objects.delete(idx)
|
||||
inc(idx)
|
||||
inc(count)
|
||||
when debugGC:
|
||||
inc(count)
|
||||
when debugGC:
|
||||
echo &"DEBUG - GC: Swept {count} objects"
|
||||
|
||||
|
@ -308,9 +311,9 @@ proc collect(self: PeonGC) =
|
|||
## Attempts to reclaim some
|
||||
## memory from unreachable
|
||||
## objects onto the heap
|
||||
let before {.used.} = self.bytesAllocated.current
|
||||
let time {.used.} = getMonoTime().ticks().float() / 1_000_000
|
||||
when debugGC:
|
||||
let before = self.bytesAllocated.current
|
||||
let time = getMonoTime().ticks().float() / 1_000_000
|
||||
echo &"DEBUG - GC: Starting collection cycle at heap size {self.bytesAllocated.current}"
|
||||
self.trace(self.markRoots())
|
||||
self.sweep()
|
||||
|
@ -793,14 +796,14 @@ proc dispatch*(self: PeonVM) =
|
|||
if self.frames.len() == 0:
|
||||
# End of the program!
|
||||
return
|
||||
self.ip = ret.uInt
|
||||
self.ip = ret.uint
|
||||
of SetResult:
|
||||
# Sets the result of the
|
||||
# current function. A Return
|
||||
# instruction will pop this
|
||||
# off the results array and
|
||||
# onto the operand stack when
|
||||
# the current function exits.
|
||||
# the current function exits
|
||||
self.results[self.frames.high()] = self.pop()
|
||||
of StoreVar:
|
||||
# Stores the value at the top of the operand stack
|
||||
|
@ -813,10 +816,12 @@ proc dispatch*(self: PeonVM) =
|
|||
else:
|
||||
self.pushc(self.pop())
|
||||
of LoadClosure:
|
||||
# Loads a closed-over variable onto the
|
||||
# stack
|
||||
# Loads a closed-over variable from the current
|
||||
# environment onto the operand stack
|
||||
self.push(self.getClosure(self.readLong().int))
|
||||
of PopClosure:
|
||||
# Discards a closed-over variable from the
|
||||
# current environment
|
||||
discard self.popClosure(self.readLong().int)
|
||||
of StoreClosure:
|
||||
# Stores/updates the value of a closed-over
|
||||
|
@ -824,8 +829,8 @@ proc dispatch*(self: PeonVM) =
|
|||
let item = self.getc(self.readLong().int)
|
||||
self.setClosure(self.readLong().int, item)
|
||||
of LoadVar:
|
||||
# Pushes a variable onto the operand
|
||||
# stack
|
||||
# Pushes a variable from the call stack
|
||||
# onto the operand stack
|
||||
self.push(self.getc(self.readLong().int))
|
||||
of NoOp:
|
||||
# Does nothing
|
||||
|
@ -863,32 +868,43 @@ proc dispatch*(self: PeonVM) =
|
|||
# Relative, backward-jump
|
||||
self.ip -= self.readLong()
|
||||
of JumpIfFalse:
|
||||
# Conditional positive jump
|
||||
# Conditional, forward-jump
|
||||
if not self.peek().bool:
|
||||
self.ip += self.readLong()
|
||||
of JumpIfTrue:
|
||||
# Conditional positive jump
|
||||
# Conditional (if the top of the stack
|
||||
# equals true), forward-jump
|
||||
let ip = self.readLong()
|
||||
if self.peek().bool:
|
||||
self.ip += ip
|
||||
of JumpIfFalsePop:
|
||||
# Conditional (if the top of the stack
|
||||
# equals false), forward-jump. Always
|
||||
# pops off the operand stack
|
||||
let ip = self.readLong()
|
||||
if not self.pop().bool:
|
||||
self.ip += ip
|
||||
of JumpIfFalseOrPop:
|
||||
# Conditional (if the top of the stack
|
||||
# equals false), forward-jump. Pops off
|
||||
# the operand stack if the value at the
|
||||
# top of the operand stack is true
|
||||
let ip = self.readLong()
|
||||
if not self.peek().bool:
|
||||
self.ip += ip
|
||||
else:
|
||||
discard self.pop()
|
||||
# Built-in operations on primitive types.
|
||||
# Note: for operations where the order of
|
||||
# the operands matters, we don't need to
|
||||
# Note that, for operations where the order
|
||||
# of the operands matters, we don't need to
|
||||
# swap the order of the calls to pop: this
|
||||
# is because operators are handled like peon
|
||||
# functions, which means the arguments are
|
||||
# already reversed on the stack when we
|
||||
# execute the instruction
|
||||
# execute the instruction. The beauty of the
|
||||
# 2's complement system is that for most integer
|
||||
# types, we don't need specialized instructions
|
||||
# to operate on them
|
||||
of Negate:
|
||||
self.push(uint64(-int64(self.pop())))
|
||||
of NegateFloat64:
|
||||
|
|
Loading…
Reference in New Issue