Skip to content

Commit

Permalink
fix: Implement LENALLOC, ADJUSTALLOC (#445)
Browse files Browse the repository at this point in the history
fixes #441
  • Loading branch information
tomsci authored Oct 5, 2024
1 parent f752deb commit a02c057
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 14 deletions.
9 changes: 7 additions & 2 deletions src/fns.lua
Original file line number Diff line number Diff line change
Expand Up @@ -856,11 +856,16 @@ function ReAlloc(stack, runtime) -- 0x4C
end

function AdjustAlloc(stack, runtime) -- 0x4D
unimplemented("fns.AdjustAlloc")
-- This API is a weird combo of realloc and memcpy
local addr, offset, sz = stack:pop(3)
local result = runtime:adjustAlloc(addr, offset, sz)
stack:push(result)
end

function LenAlloc(stack, runtime) -- 0x4E
unimplemented("fns.LenAlloc")
local ptr = stack:pop()
local result = runtime:allocLen(ptr)
stack:push(result)
end

function Ioc(stack, runtime) -- 0x4F
Expand Down
39 changes: 31 additions & 8 deletions src/memory.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function Chunk:checkRange(addr)
if addr < self.address or addr >= max then
error(fmt("Address 0x%08X out of bounds %08X-%08X", addr, self.address, max), 2)
end
return addr - self.address
end

local function word(self, idx)
Expand Down Expand Up @@ -236,6 +237,7 @@ end
function Chunk:alloc(len)
-- printf("alloc(%d) ", len)
-- printf("freeCellList before: %s ", self:freeCellListStr())
-- printf("\n")

len = (len + 3) & ~3
local freeCellPtrIdx = 0
Expand Down Expand Up @@ -305,7 +307,7 @@ function Chunk:freeCellListStr()
local list = self:freeCellList()
local parts = {}
for i, idx in ipairs(self:freeCellList()) do
parts[i] = string.format("%d+%d", idx * 4, self:getCellLen(idx))
parts[i] = string.format("%X+%d", idx * 4, self:getCellLen(idx))
end
return table.concat(parts, ",")
end
Expand Down Expand Up @@ -344,7 +346,7 @@ function Chunk:declareFreeCell(cellIdx, cellLen)
end

local nextCell = self[prev + 1]
-- printf("free(%X): prev=%X next=%X\n", cellIdx << strideshift, prev << strideshift, nextCell << strideshift)
-- printf("declareFreeCell(%X): prev=%X next=%X\n", cellIdx << strideshift, prev << strideshift, nextCell << strideshift)
self[prev + 1] = cellIdx -- prev->next = cellIdx
self[cellIdx + 1] = nextCell -- cell->next = nextCell

Expand All @@ -365,6 +367,7 @@ function Chunk:declareFreeCell(cellIdx, cellLen)
end

function Chunk:realloc(offset, sz)
-- printf("realloc(0x%X, %d) freeCellList before: %s \n", offset, sz, self:freeCellListStr())
if sz == 0 then
self:free(offset)
return nil
Expand All @@ -384,17 +387,37 @@ function Chunk:realloc(offset, sz)
return offset
else
local newOffset = self:alloc(sz)
local oldIdx = offset >> strideshift
local newIdx = newOffset >> strideshift
-- This is a little more optimised than doing a read() followed by a write()
for i = 0, (allocLen >> strideshift) - 1 do
self[newIdx + i] = self[oldIdx + i]
end
self:aligned_memcpy(newOffset, offset, allocLen)
self:free(offset)
return newOffset
end
end

local function inrange(min, val, rangeLen)
return val >= min and val < min + rangeLen
end

-- must be non-overlapping, src, dest and len must all be a multiple of chunkstride
function Chunk:aligned_memcpy(dest, src, len)
local srcIdx = src >> strideshift
local destIdx = dest >> strideshift
for i = 0, (len >> strideshift) - 1 do
self[destIdx + i] = self[srcIdx + i]
end
end

function Chunk:memmove(dest, src, len)
if inrange(src, dest, src + len) or inrange(src, dest + len, src + len) then
-- overlapping just do it the dumb way
self:write(dest, self:read(src, len))
elseif dest % chunkstride ~= 0 or src % chunkstride ~= 0 or len % chunkstride ~= 0 then
-- unaligned, ditto
self:write(dest, self:read(src, len))
else
self:aligned_memcpy(dest, src, len)
end
end

Variable = class {
_type = nil,
_chunk = nil,
Expand Down
39 changes: 35 additions & 4 deletions src/runtime.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1257,8 +1257,8 @@ end
function Runtime:addrFromInt(addr)
-- if type(addr) == "number" then
if ~addr then
self.chunk:checkRange(addr)
addr = Addr { chunk = self.chunk, offset = addr - self.chunk.address }
local offset = self.chunk:checkRange(addr)
addr = Addr { chunk = self.chunk, offset = offset }
end
return addr
end
Expand All @@ -1270,8 +1270,7 @@ end
function Runtime:realloc(addr, sz)
-- printf("Runtime:realloc(%s, %d)\n", addr, sz) --, self:getOpoStacktrace())
if addr ~= 0 then
self.chunk:checkRange(addr)
local offset = addr - self.chunk.address
local offset = self.chunk:checkRange(addr)
local newOffset = self.chunk:realloc(offset, sz)
if newOffset then
return self.chunk.address + newOffset
Expand All @@ -1285,6 +1284,38 @@ function Runtime:realloc(addr, sz)
end
end

function Runtime:allocLen(addr)
local offset = self.chunk:checkRange(addr)
return self.chunk:getAllocLen(offset)
end

function Runtime:adjustAlloc(addr, offset, sz)
local chunk = self.chunk
local cell = chunk:checkRange(addr)
local allocLen = chunk:getAllocLen(cell)
-- printf("adjustAlloc(0x%X, %X, %d)\n", cell, offset, sz)
assert(offset >= 0, "Bad offset to adjustAlloc")
if sz == 0 then
-- nothing to do?
return addr
elseif sz < 0 then
sz = -sz -- Makes logic easier to understand below
assert(offset - sz < allocLen)
-- close gap at offset, ie copy everything from offset+sz to offset
chunk:memmove(cell + offset, cell + offset + sz, allocLen - offset - sz)
return chunk.address + chunk:realloc(cell, allocLen - sz)
else
-- Add gap at offset
local newCell = chunk:realloc(cell, allocLen + sz)
if newCell then
chunk:memmove(newCell + offset + sz, newCell + offset, allocLen - offset)
return chunk.address + newCell
else
return 0
end
end
end

function runOpo(fileName, procName, iohandler, verbose)
local data, err = iohandler.fsop("read", fileName)
if not data then
Expand Down

0 comments on commit a02c057

Please sign in to comment.