Skip to content

Commit a02c057

Browse files
authored
fix: Implement LENALLOC, ADJUSTALLOC (#445)
fixes #441
1 parent f752deb commit a02c057

File tree

3 files changed

+73
-14
lines changed

3 files changed

+73
-14
lines changed

src/fns.lua

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -856,11 +856,16 @@ function ReAlloc(stack, runtime) -- 0x4C
856856
end
857857

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

862865
function LenAlloc(stack, runtime) -- 0x4E
863-
unimplemented("fns.LenAlloc")
866+
local ptr = stack:pop()
867+
local result = runtime:allocLen(ptr)
868+
stack:push(result)
864869
end
865870

866871
function Ioc(stack, runtime) -- 0x4F

src/memory.lua

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ function Chunk:checkRange(addr)
6868
if addr < self.address or addr >= max then
6969
error(fmt("Address 0x%08X out of bounds %08X-%08X", addr, self.address, max), 2)
7070
end
71+
return addr - self.address
7172
end
7273

7374
local function word(self, idx)
@@ -236,6 +237,7 @@ end
236237
function Chunk:alloc(len)
237238
-- printf("alloc(%d) ", len)
238239
-- printf("freeCellList before: %s ", self:freeCellListStr())
240+
-- printf("\n")
239241

240242
len = (len + 3) & ~3
241243
local freeCellPtrIdx = 0
@@ -305,7 +307,7 @@ function Chunk:freeCellListStr()
305307
local list = self:freeCellList()
306308
local parts = {}
307309
for i, idx in ipairs(self:freeCellList()) do
308-
parts[i] = string.format("%d+%d", idx * 4, self:getCellLen(idx))
310+
parts[i] = string.format("%X+%d", idx * 4, self:getCellLen(idx))
309311
end
310312
return table.concat(parts, ",")
311313
end
@@ -344,7 +346,7 @@ function Chunk:declareFreeCell(cellIdx, cellLen)
344346
end
345347

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

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

367369
function Chunk:realloc(offset, sz)
370+
-- printf("realloc(0x%X, %d) freeCellList before: %s \n", offset, sz, self:freeCellListStr())
368371
if sz == 0 then
369372
self:free(offset)
370373
return nil
@@ -384,17 +387,37 @@ function Chunk:realloc(offset, sz)
384387
return offset
385388
else
386389
local newOffset = self:alloc(sz)
387-
local oldIdx = offset >> strideshift
388-
local newIdx = newOffset >> strideshift
389-
-- This is a little more optimised than doing a read() followed by a write()
390-
for i = 0, (allocLen >> strideshift) - 1 do
391-
self[newIdx + i] = self[oldIdx + i]
392-
end
390+
self:aligned_memcpy(newOffset, offset, allocLen)
393391
self:free(offset)
394392
return newOffset
395393
end
396394
end
397395

396+
local function inrange(min, val, rangeLen)
397+
return val >= min and val < min + rangeLen
398+
end
399+
400+
-- must be non-overlapping, src, dest and len must all be a multiple of chunkstride
401+
function Chunk:aligned_memcpy(dest, src, len)
402+
local srcIdx = src >> strideshift
403+
local destIdx = dest >> strideshift
404+
for i = 0, (len >> strideshift) - 1 do
405+
self[destIdx + i] = self[srcIdx + i]
406+
end
407+
end
408+
409+
function Chunk:memmove(dest, src, len)
410+
if inrange(src, dest, src + len) or inrange(src, dest + len, src + len) then
411+
-- overlapping just do it the dumb way
412+
self:write(dest, self:read(src, len))
413+
elseif dest % chunkstride ~= 0 or src % chunkstride ~= 0 or len % chunkstride ~= 0 then
414+
-- unaligned, ditto
415+
self:write(dest, self:read(src, len))
416+
else
417+
self:aligned_memcpy(dest, src, len)
418+
end
419+
end
420+
398421
Variable = class {
399422
_type = nil,
400423
_chunk = nil,

src/runtime.lua

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,8 +1257,8 @@ end
12571257
function Runtime:addrFromInt(addr)
12581258
-- if type(addr) == "number" then
12591259
if ~addr then
1260-
self.chunk:checkRange(addr)
1261-
addr = Addr { chunk = self.chunk, offset = addr - self.chunk.address }
1260+
local offset = self.chunk:checkRange(addr)
1261+
addr = Addr { chunk = self.chunk, offset = offset }
12621262
end
12631263
return addr
12641264
end
@@ -1270,8 +1270,7 @@ end
12701270
function Runtime:realloc(addr, sz)
12711271
-- printf("Runtime:realloc(%s, %d)\n", addr, sz) --, self:getOpoStacktrace())
12721272
if addr ~= 0 then
1273-
self.chunk:checkRange(addr)
1274-
local offset = addr - self.chunk.address
1273+
local offset = self.chunk:checkRange(addr)
12751274
local newOffset = self.chunk:realloc(offset, sz)
12761275
if newOffset then
12771276
return self.chunk.address + newOffset
@@ -1285,6 +1284,38 @@ function Runtime:realloc(addr, sz)
12851284
end
12861285
end
12871286

1287+
function Runtime:allocLen(addr)
1288+
local offset = self.chunk:checkRange(addr)
1289+
return self.chunk:getAllocLen(offset)
1290+
end
1291+
1292+
function Runtime:adjustAlloc(addr, offset, sz)
1293+
local chunk = self.chunk
1294+
local cell = chunk:checkRange(addr)
1295+
local allocLen = chunk:getAllocLen(cell)
1296+
-- printf("adjustAlloc(0x%X, %X, %d)\n", cell, offset, sz)
1297+
assert(offset >= 0, "Bad offset to adjustAlloc")
1298+
if sz == 0 then
1299+
-- nothing to do?
1300+
return addr
1301+
elseif sz < 0 then
1302+
sz = -sz -- Makes logic easier to understand below
1303+
assert(offset - sz < allocLen)
1304+
-- close gap at offset, ie copy everything from offset+sz to offset
1305+
chunk:memmove(cell + offset, cell + offset + sz, allocLen - offset - sz)
1306+
return chunk.address + chunk:realloc(cell, allocLen - sz)
1307+
else
1308+
-- Add gap at offset
1309+
local newCell = chunk:realloc(cell, allocLen + sz)
1310+
if newCell then
1311+
chunk:memmove(newCell + offset + sz, newCell + offset, allocLen - offset)
1312+
return chunk.address + newCell
1313+
else
1314+
return 0
1315+
end
1316+
end
1317+
end
1318+
12881319
function runOpo(fileName, procName, iohandler, verbose)
12891320
local data, err = iohandler.fsop("read", fileName)
12901321
if not data then

0 commit comments

Comments
 (0)