Skip to content

Commit

Permalink
Bug fixes in GC
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Feb 9, 2020
1 parent 0e240cd commit 26d7eef
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 66 deletions.
73 changes: 36 additions & 37 deletions lib/gc.nelua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ local function setjmp(env: jmp_buf) <cimport,nodecl> end

local allocator = @generic_allocator

local GCFlags = @enum(usize) {
global GCFlags = @enum(usize) {
MARK = 1,
ROOT = 2,
LEAF = 4
Expand Down Expand Up @@ -208,6 +208,12 @@ function GC:_resize_less(): boolean
end
end

function GC:_unmark_all() <noinline>
for i:usize=0,<self.nslots do
self.items[i].flags = self.items[i].flags & ~GCFlags.MARK
end
end

function GC:_mark_ptr(ptr: pointer)
if (@usize)(ptr) < self.minptr or (@usize)(ptr) > self.maxptr then
return
Expand Down Expand Up @@ -243,21 +249,11 @@ function GC:_mark_stack() <noinline, cattribute 'no_sanitize(("address"))'>
local stk: pointer
local bot: usize = (@usize)(self.bottom)
local top: usize = (@usize)(&stk)

if bot == top then
return
end

if bot < top then
for pi:usize=top,>=bot,-#@pointer do
self:_mark_ptr($(@pointer*)(pi))
end
bot, top = top, bot
end

if bot > top then
for pi:usize=top,<=bot,#@pointer do
self:_mark_ptr($(@pointer*)(pi))
end
for pi:usize=top,<=bot,#@pointer do
self:_mark_ptr($(@pointer*)(pi))
end
end

Expand All @@ -266,6 +262,8 @@ function GC:_mark() <noinline>
return
end

self:_unmark_all()

for i:usize=0,<self.nslots do
if self.items[i].hash == 0 or
self.items[i].flags & GCFlags.MARK ~= 0 then
Expand All @@ -276,10 +274,9 @@ function GC:_mark() <noinline>
if self.items[i].flags & GCFlags.LEAF ~= 0 then
continue
end
for k:usize=0,<self.items[i].size//#@pointer do
for k:usize=0,<self.items[i].size//(@usize)(#@pointer) do
self:_mark_ptr(((@pointer[0]*)(self.items[i].ptr))[k])
end
continue
end
end

Expand All @@ -303,7 +300,7 @@ function GC:_sweep() <noinline>
end
end

self.frees = allocator.spanrealloc0(self.frees, self.nfrees)
self.frees = allocator.spanrealloc(self.frees, self.nfrees)
if self.frees.size == 0 then
return
end
Expand Down Expand Up @@ -337,14 +334,7 @@ function GC:_sweep() <noinline>
self.nitems = self.nitems - 1
end

for j:usize=0,<self.nslots do
if self.items[j].hash ~= 0 then
if self.items[j].flags & GCFlags.MARK ~= 0 then
self.items[j].flags = self.items[j].flags & ~GCFlags.MARK
end
end
end

self:_unmark_all()
self:_resize_less()

self.mitems = self.nitems + (@usize)(self.nitems * self.sweepfactor) + 1
Expand Down Expand Up @@ -393,7 +383,7 @@ function GC:run()
self:_sweep()
end

function GC:add(ptr: pointer, size: usize, flags: usize, finalizer: FinalizerPtr): pointer
function GC:add(ptr: pointer, size: usize, flags: usize, finalizer: FinalizerPtr): boolean
self.nitems = self.nitems + 1

local uptr: usize = (@usize)(ptr)
Expand All @@ -409,11 +399,10 @@ function GC:add(ptr: pointer, size: usize, flags: usize, finalizer: FinalizerPtr
if not self.paused and self.nitems > self.mitems then
self:run()
end
return ptr
return true
else
self.nitems = self.nitems - 1
allocator.dealloc(ptr)
return nilptr
return false
end
end

Expand All @@ -423,20 +412,24 @@ function GC:rem(ptr: pointer)
self.mitems = self.nitems + self.nitems // 2 + 1
end

function GC:alloc_opt(size: usize, flags: usize, finalizer: FinalizerPtr): pointer
local ptr: pointer = allocator.alloc(size)
function GC:_alloc(ptr: pointer, size: usize, flags: usize, finalizer: FinalizerPtr): pointer <inline>
if ptr then
ptr = self:add(ptr, size, flags, finalizer)
if not self:add(ptr, size, flags, finalizer) then
allocator.dealloc(ptr)
ptr = nilptr
end
end
return ptr
end

function GC:alloc_opt(size: usize, flags: usize, finalizer: FinalizerPtr): pointer
local ptr: pointer = allocator.alloc(size)
return self:_alloc(ptr, size, flags, finalizer)
end

function GC:alloc0_opt(size: usize, flags: usize, finalizer: FinalizerPtr): pointer
local ptr: pointer = allocator.alloc0(size)
if ptr then
ptr = self:add(ptr, size, flags, finalizer)
end
return ptr
return self:_alloc(ptr, size, flags, finalizer)
end

function GC:alloc(size: usize): pointer
Expand All @@ -454,7 +447,10 @@ function GC:_realloc(qtr: pointer, ptr: pointer, size: usize): pointer <inline>
end

if not ptr then
self:add(qtr, size, 0, nilptr)
if not self:add(qtr, size, 0, nilptr) then
allocator.dealloc(qtr)
qtr = nilptr
end
return qtr
end

Expand Down Expand Up @@ -536,6 +532,9 @@ global gc = GC{}

local function nelua_main(): cint <cimport,nodecl> end

local static_top: pointer <volatile>
local static_bottom: pointer <volatile>

local function main(argc: cint, argv: cchar**): cint <entrypoint>
gc:start(&argc)
local ret: cint = nelua_main()
Expand Down
61 changes: 32 additions & 29 deletions lib/myarraytable.nelua
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,29 @@ local allocator = @gc_allocator
## local memoize = require 'nelua.utils.memoize'
## myarraytable = hygienize(memoize(function(T)
local T = @#[T]#
local ArrayTableImpl <codename #['nelua_ArrayTableImpl_'..T.name]#> = @record {
local ArrayTableImplT <codename #['nelua_ArrayTableImpl_'..T.name]#> = @record {
size: usize,
data: span(T)
}
local ArrayTable <codename #['nelua_ArrayTable_'..T.name]#> = @record{
impl: ArrayTableImpl*
global ArrayTableT <codename #['nelua_ArrayTable_'..T.name]#> = @record{
impl: ArrayTableImplT*
}

function ArrayTable:_init() <inline>
function ArrayTableT:init() <inline>
if unlikely(not self.impl) then
self.impl = (@ArrayTableImpl*)(allocator.alloc0(#ArrayTableImpl))
self.impl = (@ArrayTableImplT*)(allocator.alloc0(#ArrayTableImplT))
end
end

function ArrayTable:_grow() <noinline>
function ArrayTableT:reset()
if likely(self.impl) then
allocator.spandealloc(self.impl.data)
allocator.dealloc(self.impl)
self.impl = nilptr
end
end

function ArrayTableT:_grow() <noinline>
local cap: usize
if self.impl.data.size ~= 0 then
cap = self.impl.data.size * 2
Expand All @@ -35,16 +43,16 @@ local allocator = @gc_allocator
self.impl.data = allocator.spanrealloc(self.impl.data, cap)
end

function ArrayTable:reserve(n: usize <autocast>) <noinline>
self:_init()
function ArrayTableT:reserve(n: usize <autocast>) <noinline>
self:init()
local cap = n + 1
if self.impl.data.size < cap then
self.impl.data = allocator.spanrealloc(self.impl.data, cap)
end
end

function ArrayTable:resize(n: usize <autocast>, v: T)
self:_init()
function ArrayTableT:resize(n: usize <autocast>, v: T)
self:init()
local addn = n - self.impl.size
if addn > 0 then
self:reserve(n)
Expand All @@ -55,38 +63,33 @@ local allocator = @gc_allocator
end
end

function ArrayTable:clear()
function ArrayTableT:clear()
if likely(self.impl) then
self.impl.size = 0
if likely(self.impl.data.size > 0) then
memory.zero(&self.impl.data[0], #T)
end
end
end

function ArrayTable:reset()
if likely(self.impl) then
allocator.spandealloc(self.impl.data)
allocator.dealloc(self.impl)
self.impl = nilptr
end
end

function ArrayTable:push(v: T) <inline>
self:_init()
function ArrayTableT:push(v: T) <inline>
self:init()
self.impl.size = self.impl.size + 1
if unlikely(self.impl.size + 1 >= self.impl.data.size) then
self:_grow()
end
self.impl.data[self.impl.size] = v
end

function ArrayTable:pop(): T <inline>
function ArrayTableT:pop(): T <inline>
check(self.impl and self.impl.size > 0, 'arraytable.pop: length is 0')
local i = self.impl.size
self.impl.size = self.impl.size - 1
return self.impl.data[i]
end

function ArrayTable:at(i: usize <autocast>): T* <inline>
self:_init()
function ArrayTableT:at(i: usize <autocast>): T* <inline>
self:init()
if unlikely(i > self.impl.size) then
check(i == self.impl.size + 1, 'arraytable.at: index out of range')
self.impl.size = self.impl.size + 1
Expand All @@ -98,8 +101,8 @@ local allocator = @gc_allocator
return &self.impl.data[i]
end

function ArrayTable:set(i: usize <autocast>, v: T) <inline>
self:_init()
function ArrayTableT:set(i: usize <autocast>, v: T) <inline>
self:init()
if unlikely(i > self.impl.size) then
check(i == self.impl.size + 1, 'arraytable.at: index out of range')
self.impl.size = self.impl.size + 1
Expand All @@ -110,7 +113,7 @@ local allocator = @gc_allocator
self.impl.data[i] = v
end

function ArrayTable:get(i: usize <autocast>): T <inline>
function ArrayTableT:get(i: usize <autocast>): T <inline>
if unlikely(i == 0 and (not self.impl or self.impl.data.size == 0)) then
local v: T
return v
Expand All @@ -120,12 +123,12 @@ local allocator = @gc_allocator
end
end

function ArrayTable:len(): isize <inline>
function ArrayTableT:len(): isize <inline>
if unlikely(not self.impl) then
return 0
end
return (@isize)(self.impl.size)
end

## return ArrayTable
## return ArrayTableT
## end))

0 comments on commit 26d7eef

Please sign in to comment.