-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
Hey!
I've been thinking about adding heap (and stack) support for the interpreter, but I think it would be a good idea to have a runtest test suite before doing that.
To that end, I've been thinking about how to integrate heaps with runtests, and this is what I've come up with, but would like to discuss and gather some feedback before proceeding with implementation.
Benefit
We get better test coverage both for the interpreter and all cranelift backends.
Implementation
My idea would be to allocate each heap in a separate Vec, and pass pointers to it in a vmctx struct. We would do this
in the trampoline whenever a function has heap annotations and a vmctx argument.
function %heap_load_store_test(i64 vmctx, i32, i32) -> i32 {
gv0 = vmctx
gv1 = load.i64 notrap aligned gv0+0
gv2 = load.i64 notrap aligned gv0+8
gv3 = load.i64 notrap aligned gv0+16
heap0 = static gv1, min 0x1000, bound 0x1_0000_0000, offset_guard 0
heap1 = dynamic gv2, bound gv3, offset_guard 0
block0(v0: i64, v1: i32, v2: i32):
v3 = iconst.i64 0
v4 = heap_addr.i64 heap0, v3, 4
store.i32 v1, v4
v6 = load.i32 v4
v7 = iadd.i32 v6, v2
return v7
}
; run: %heap_load_store_test(1, 2) == 3
In this example we have two heaps, so we would allocate a struct that holds info about the location of these heaps
and pass its pointer as the first argument to the function
The first heap (static) is preallocated with the minimum size of 4096 bytes. I don't think we have a way to resize
it, so we would always trap on accesses past the minimum size. This heap only requires the base pointer, so
we only allocate 8 bytes of the vmctx struct for the base pointer.
The second heap (dynamic) requires two pointers (base + bounds), so we reserve 16 bytes in the vmctx struct and pass
the base and bounds pointers. Here we can reserve a default size like 16KB. Again we don't have a way to resize it dynamically, so we just don't do that.
I think the syntax for what I described above is correct in the example function, but it might not be, so take it with
a grain of salt.
I don't like that with this design the runtest arguments no longer match what ends up in the function. But if this is
restricted to heap tests it shouldn't be too bad.
Another note is that although we don't have to always use the first argument for vmctx, it would be nicer if we
restricted (by design or by convention) it that way so that things would be less confusing.
Questions:
- What happens when we have heap annotations but no
vmctxargument? My opinion here is that we just don't allocate anything. - Is there a way for us to grow heaps in the middle of a test? How is this done in other virtual machines?
Alternatives
We can not do this and implement heap tests in the interpreter as regular rust tests. This would be a lot more verbose and would lose the benefit of testing other backends.