Memory allocator, switch to wasmtime

main
Ashelyn Dawn 11 months ago
parent 2537fa8c41
commit 93c790a4ef

@ -30,14 +30,15 @@ echo "$NONIMPORTS" >> $INTERMEDIATE
echo "$EPILOGUE" >> $INTERMEDIATE
# test file
wasmer compile -o ./output.wasmu $INTERMEDIATE
wat2wasm $INTERMEDIATE
result=$?
mv intermediate.wasm output.wasm
if [ 0 -ne $result ]; then
echo "Build failed, printing generated wasm:"
cat $INTERMEDIATE
echo "Build failed"
# cat $INTERMEDIATE
exit $?
else
echo "Build succeeded, running:"
wasmer run ./output.wasmu
wasmtime ./output.wasm --wasi-modules wasi-common --tcplisten 127.0.0.1:8080
fi

@ -1,7 +1,24 @@
(data $hello (i32.const 20) "Hello world.\0A")
(import "wasi_unstable" "proc_exit" (func $proc_exit (param i32)))
(data $hello "Hello world.\0A")
(import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32)))
(func $start (export "_start") (result i32)
i32.const 20 ;; location
(local $stringLocation i32)
call $memory_init
i32.const 13
call $memory_alloc
local.set $stringLocation
;; copy string into memory
local.get $stringLocation ;; dest
i32.const 0 ;; index into string
i32.const 13 ;; length
memory.init $hello
;; print
local.get $stringLocation ;; location
i32.const 13 ;; length
call $print

@ -2,26 +2,55 @@
(import "wasi_unstable" "fd_write" (func $fd_write (param $file_descriptor i32) (param $io_vectors i32) (param $io_vecnum i32) (param $num_written_ptr i32) (result i32)))
(func $print (param $location i32) (param $length i32) (result i32)
;; create struct at location 0
i32.const 0
(local $structLoc i32)
(local $resultLoc i32)
(local $resultCode i32)
i32.const 8 ;; 2 x 4bytes per i32
call $memory_alloc
local.set $structLoc
i32.const 4
call $memory_alloc
local.set $resultLoc
;; put location at offset 0
local.get $structLoc
local.get $location
i32.store
;; put length at offset 4
local.get $structLoc
i32.const 4
i32.add
local.get $length
i32.store
;; file descriptor
i32.const 1
;; call params
i32.const 1 ;; file file_descriptor
local.get $structLoc ;; array pointer
i32.const 1 ;; array length
local.get $resultLoc ;; result pointer
;; iovs array pointer
i32.const 0
call $fd_write
local.tee $resultCode
;; iovs array length
i32.const 1
;; if 0 code, make sure all bytes were written
i32.eqz
if
local.get $resultLoc
local.get $length
i32.lt_u
if
i32.const 1
return
end
;; where to write length written
i32.const 200
i32.const 0
return
end
call $fd_write
;; otherwise return code
local.get $resultCode
return
)

@ -0,0 +1,218 @@
(func $memory_init
(local $memorySize i32)
;; starting location
i32.const 4
;; get num pages
memory.size
;; shift left by 16 bits to get byte size
i32.const 16
i32.shl
i32.const 4
i32.sub
;; place start/end tags
call $memory_markBlockSize
)
(func $memory_alloc (export "alloc") (param $requestedBytes i32) (result i32)
(local $blockAddr i32)
local.get $requestedBytes
call $memory_findFreeBlock
local.tee $blockAddr
;; check if we found a block
i32.eqz
if
i32.const 0
return
end
;; potentially split block
local.get $blockAddr
local.get $requestedBytes
call $memory_splitFreeBlock
;; mark used
local.get $blockAddr
call $memory_markBlockUsed
;; offset boundary address to get usable pointer
local.get $blockAddr
i32.const 4
i32.add
return
)
;; returns address of boundary word for first free block
(func $memory_findFreeBlock (export "findFree") (param $minimumBytes i32) (result i32)
(local $memorySize i32)
(local $currentBlock i32)
;; get memory size in bytes
memory.size
i32.const 16 ;; convert pages to bytes
i32.shl
local.set $memorySize
;; start 4 bytes in so we don't ever get a 0 address
i32.const 4
local.set $currentBlock
block $exitBlock
loop $blockLoop
;; make sure we're not past the end
local.get $currentBlock
local.get $memorySize
i32.ge_u
br_if $exitBlock
;; check if current block is used (result pushed to stack)
local.get $currentBlock
call $memory_isBlockUsed
;; check if current block is smaller than we need (result pushed to stack)
local.get $currentBlock
call $memory_getUsableSizeOfBlock
local.get $minimumBytes
i32.lt_u
;; if either is true
i32.or
if
;; move pointer
local.get $currentBlock
i32.load ;; get size
i32.const -2 ;; mask least-significant bit
i32.and
local.get $currentBlock
i32.add
local.set $currentBlock
;; continue loop
br $blockLoop
end
;; block is free and big enough
local.get $currentBlock
return
end
end
;; reached the end of memory, cannot find a block
i32.const 0
return
)
;; checks to see if block at given address can be split into part of at least $minimumBytes
;; and splits if it is able
(func $memory_splitFreeBlock (export "splitFree") (param $boundaryTagAddress i32) (param $minimumBytes i32)
(local $desiredSize i32)
(local $oldBlockSize i32)
(local $newBlockSize i32)
;; desiredSize = minimumBytes + tags
local.get $minimumBytes
i32.const 8
i32.add
local.set $desiredSize
;; oldBlockSize
local.get $boundaryTagAddress
i32.load
i32.const -2
i32.and
local.set $oldBlockSize
;; newBlockSize (rounding up to nearest 16-byte chunk)
local.get $desiredSize
i32.const 15
i32.add
i32.const -16
i32.and
local.set $newBlockSize
;; mark new block
local.get $boundaryTagAddress
local.get $newBlockSize
call $memory_markBlockSize
;; mark remaining if it exists
local.get $newBlockSize
local.get $oldBlockSize
i32.lt_u
if
;; address
local.get $boundaryTagAddress
local.get $newBlockSize
i32.add
;; remaining size
local.get $oldBlockSize
local.get $newBlockSize
i32.sub
call $memory_markBlockSize
end
)
;; marks a block as used
(func $memory_markBlockUsed (export "markUsed") (param $boundaryTagAddress i32)
(local $blockSize i32)
local.get $boundaryTagAddress
i32.load
i32.const -2
i32.and
local.set $blockSize
local.get $boundaryTagAddress
local.get $blockSize
i32.const 1
i32.or
i32.store
local.get $boundaryTagAddress
local.get $blockSize
i32.add
i32.const 4
i32.sub
local.get $blockSize
i32.const 1
i32.or
i32.store
)
;; sets boundary tags for unused block
(func $memory_markBlockSize (export "markSize") (param $boundaryTagAddress i32) (param $sizeWithTags i32)
;; put size at tag location
local.get $boundaryTagAddress
local.get $sizeWithTags
i32.store
;; put size at tag + size - 4
local.get $boundaryTagAddress
local.get $sizeWithTags
i32.add
i32.const 4
i32.sub
local.get $sizeWithTags
i32.store
)
;; check if block at given boundary tag address is used
(func $memory_isBlockUsed (export "isUsed") (param $boundaryTagAddress i32) (result i32)
local.get $boundaryTagAddress
i32.load
i32.const 1
i32.and
)
(func $memory_getUsableSizeOfBlock (export "getUsableSize") (param $boundaryTagAddress i32) (result i32)
local.get $boundaryTagAddress
i32.load
i32.const -2
i32.and
i32.const 8
i32.sub
)
Loading…
Cancel
Save