-
Notifications
You must be signed in to change notification settings - Fork 12
Implement MemoryFill and MemoryCopy bulk memory ops
#29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
also corrected textual syntax for `Memory{Size,Grow}` to
be conforming with https://webassembly.github.io/spec/core/text/instructions.html#memory-instructions
Memory* opsMemoryFill and MemoryCopy bulk memory ops
cb56cce to
e3d154d
Compare
|
@nomeata I am not really in the know about how close we have to follow the spec and how to test new instructions. Can you have a look at what I have now and give some guidance about how to test this? |
|
We can run the official test suite. Does that not include tests for these instructions? |
this is shamelessly frobbed from https://github.com/WebAssembly/testsuite/blob/main/bulk.wast (the official test suite) but shortened to only those two instructions
|
I found the official tests too, but like 66c7510 they contain Is there a special trick, or another tool to run these? |
|
Yes, these are wast scripts, that's a superset of wat. There is a test runner for them included somewhere in the test suite of winter (which runs the official test suite, maybe if you set an envvar), though. I paged out most of the details. |
nomeata
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are Wasm files committed; intentionally?
I assume the code was ported, where applicable, from the ocaml reference implementation? (This is desirable as it makes adding more feature in the future easier.)
|
I have blown away all that stuff (but I could bring it back if there is a good reason for it). My hunch is that it was needed while original development. Now running |
nomeata
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I must have misread the github diff, it looked as if some binary files were chnaged but not deleted.
Co-authored-by: Bas van Dijk <bas@van.dijk.ch>
|
The But I don't think this is related to my changes. But somehow it is different! When running from I get Mystery resolved: it is due to the |
…ding `--enable-bulk-memory` by making it possible to pass language flags per suite
| (MemoryFill, I32 0 : _ : I32 dst : vs') -> {-# SCC step_MemoryFill #-} do | ||
| inst <- getFrameInst | ||
| mem <- lift $ memory inst (0 @@ at) | ||
| -- Zero len with offset out-of-bounds at the end of memory is allowed | ||
| sz <- lift $ lift $ Memory.size mem | ||
| if Memory.pageSize * sz >= dst | ||
| then k vs' es | ||
| else k vs' (Trapping (memoryErrorString Memory.MemoryBoundsError) @@ at : es) | ||
|
|
||
| (MemoryFill, I32 cnt : v : I32 dst : vs') -> {-# SCC step_MemoryFill #-} do | ||
| inst <- getFrameInst | ||
| mem <- lift $ memory inst (0 @@ at) | ||
| let [addr, count] = fromIntegral . i64_extend_u_i32 . fromIntegral <$> [dst, cnt] | ||
| if addr + count > 2^32 | ||
| then k vs' (Trapping (memoryErrorString Memory.MemoryBoundsError) @@ at : es) | ||
| else do | ||
| eres <- lift $ lift $ runExceptT $ mapM_ (\off -> Memory.storePacked Pack8 mem addr off v) [0 .. pred cnt] | ||
| case eres of | ||
| Right () -> k vs' es | ||
| Left exn -> k vs' (Trapping (memoryErrorString exn) @@ at : es) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks quite different from the reference code in
https://github.com/WebAssembly/spec/blob/ffb5e3b40db7a45237d4e2fc972c1552ac4abef5/interpreter/exec/eval.ml#L413-L428
(and likewise below)
The design of winter is to be a pretty much direct port, so that chances are good to get the semantics right, and also to be able to follow and apply subsequent changes easily.
We have occasionally deviated, for performance reasons (e.g. https://www.joachim-breitner.de/blog/765-Faster_Winter_7__The_Zipper). Is this the reason here? Maybe worth adding a comment here… hmm, but I see you aren’t still implementing this to byte-wise operations here.
So why not just follow the logic of the reference code directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I didn't even look at the other reference :-)
Will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at that reference implementation makes me think it is written with proof assistants in mind. It lowers the complex instructions to simple ones and stucturally "smaller" identical ones. There is a case of MemoryCopy that isn't even tail recursive. So to make this remotely performant we'll have to rewrite these anyway. Otherwise even the Rust-style "do prefix and suffix bytewise and the inner part u64-wise" will be executing faster.
| putStrLn $ "Using wasm MVP spec test directory: " ++ testDirMVP | ||
| putStrLn $ "Using wasm spec test directory: " ++ testDir |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need two versions of the test suite? Can we not simply run the latest, possibly excluding new tests that we don't support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I had to disable too many tests that won't run in the new suite, and became concerned about regressing on those.
Adding support for the two most popular bulk memory operations:
MemoryFillandMemoryCopy. Imported test suite in a newer version that also exercises these new instructions. Added an exclusion list for tests from the new suite that would need features thatwinterdoesn't support yet, and kept the old suite wholesale.Stuff to do:
1.1.0type Offset = Int32should this beNat32?cnt > 0inMemoryFill,MemoryCopyMemoryCopyelem.wastfailing from the MVP suite? — it doesn'tseem to be related.test/wasmandtest/wastdirectories for? — I have nuked them for now.