diff options
| author | Henry Gressmann <mail@henrygressmann.de> | 2024-05-30 01:16:56 +0200 |
|---|---|---|
| committer | Henry Gressmann <mail@henrygressmann.de> | 2024-05-30 01:16:56 +0200 |
| commit | 7c3fd68f703d944b05dcea08f3a46c59b41503f4 (patch) | |
| tree | 4588645c28ea9775ae39f4875b019f72269dbb6f | |
| parent | ffb1e095fc1d6a2d54cc7637797c625dee6ebe6a (diff) | |
chore: cleanup
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
| -rw-r--r-- | .cargo/config.toml | 8 | ||||
| -rw-r--r-- | BENCHMARKS.md | 2 | ||||
| -rw-r--r-- | Cargo.lock | 421 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | benchmarks/benches/argon2id.rs | 2 | ||||
| -rw-r--r-- | benchmarks/benches/fibonacci.rs | 6 | ||||
| -rw-r--r-- | benchmarks/benches/selfhosted.rs | 18 | ||||
| -rw-r--r-- | crates/parser/src/visit.rs | 64 | ||||
| -rw-r--r-- | crates/tinywasm/Cargo.toml | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/boxvec.rs | 12 | ||||
| -rw-r--r-- | crates/tinywasm/src/instance.rs | 33 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/interpreter/macros.rs | 41 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/interpreter/mod.rs | 148 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/raw.rs | 19 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/call_stack.rs | 39 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/value_stack.rs | 37 | ||||
| -rw-r--r-- | crates/tinywasm/src/store/memory.rs | 45 | ||||
| -rw-r--r-- | crates/tinywasm/src/store/mod.rs | 20 | ||||
| -rw-r--r-- | crates/types/src/instructions.rs | 12 | ||||
| -rwxr-xr-x | examples/rust/build.sh | 2 | ||||
| -rw-r--r-- | scripts/Cargo.toml | 2 | ||||
| -rw-r--r-- | scripts/src/bin/generate-charts/progress.rs | 1 |
22 files changed, 276 insertions, 660 deletions
diff --git a/.cargo/config.toml b/.cargo/config.toml index be912c8..2470377 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -8,7 +8,7 @@ test-wast-release="test --package tinywasm --test test-wast --release -- --enabl generate-charts="run --package scripts --bin generate-charts --release" benchmark="bench -p benchmarks --bench" -# # enable for linux perf -# [target.x86_64-unknown-linux-gnu] -# linker="/usr/bin/clang" -# rustflags=["-Clink-arg=-fuse-ld=lld", "-Clink-arg=-Wl,--no-rosegment"] +# enable for linux perf +[target.x86_64-unknown-linux-gnu] +linker="/usr/bin/clang" +rustflags=["-Clink-arg=-fuse-ld=lld", "-Clink-arg=-Wl,--no-rosegment"] diff --git a/BENCHMARKS.md b/BENCHMARKS.md index 50df853..7b094d7 100644 --- a/BENCHMARKS.md +++ b/BENCHMARKS.md @@ -42,7 +42,7 @@ All runtimes are compiled with the following settings: | `selfhosted` | `0.05ms` | ` 7.93ms` | ` 7.54ms` | `512.45ms` | > Note that parsing is still pretty slow, especially for the `selfhosted` benchmark, taking up `~6ms` for TinyWasm. -> This can be improved by using the `archive` feature, which pre-parses the WebAssembly file into tinywasm's custom bytecode format. +> This can be improved by using the `archive` feature, which pre-compiles the WebAssembly file into tinywasm's internal bytecode format. ### Fib @@ -50,21 +50,6 @@ dependencies = [ ] [[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -322,12 +307,6 @@ dependencies = [ ] [[package]] -name = "bytemuck" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" - -[[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -370,20 +349,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-targets", -] - -[[package]] name = "ciborium" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -478,70 +443,12 @@ dependencies = [ ] [[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] name = "colorchoice" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "core-graphics" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "libc", -] - -[[package]] -name = "core-text" -version = "20.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" -dependencies = [ - "core-foundation", - "core-graphics", - "foreign-types", - "libc", -] - -[[package]] name = "corosensei" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -742,16 +649,6 @@ dependencies = [ ] [[package]] -name = "cstr" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68523903c8ae5aacfa32a0d9ae60cadeb764e1da14ee0d26b1f3089f13a54636" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] name = "darling" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -887,36 +784,6 @@ dependencies = [ ] [[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dlib" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" -dependencies = [ - "libloading", -] - -[[package]] name = "document-features" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -932,18 +799,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] -name = "dwrote" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" -dependencies = [ - "lazy_static", - "libc", - "winapi", - "wio", -] - -[[package]] name = "dyn-clone" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1074,15 +929,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] -name = "fdeflate" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" -dependencies = [ - "simd-adler32", -] - -[[package]] name = "filetime" version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1105,70 +951,12 @@ dependencies = [ ] [[package]] -name = "float-ord" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" - -[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "font-kit" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2845a73bbd781e691ab7c2a028c579727cd254942e8ced57ff73e0eafd60de87" -dependencies = [ - "bitflags 2.5.0", - "byteorder", - "core-foundation", - "core-graphics", - "core-text", - "dirs-next", - "dwrote", - "float-ord", - "freetype-sys", - "lazy_static", - "libc", - "log", - "pathfinder_geometry", - "pathfinder_simd", - "walkdir", - "winapi", - "yeslogic-fontconfig-sys", -] - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - -[[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1178,17 +966,6 @@ dependencies = [ ] [[package]] -name = "freetype-sys" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] name = "funty" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1227,16 +1004,6 @@ dependencies = [ ] [[package]] -name = "gif" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] name = "gimli" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1325,29 +1092,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1364,20 +1108,6 @@ dependencies = [ ] [[package]] -name = "image" -version = "0.24.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "jpeg-decoder", - "num-traits", - "png", -] - -[[package]] name = "indenter" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1444,12 +1174,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" - -[[package]] name = "js-sys" version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1477,32 +1201,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] -name = "libloading" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" -dependencies = [ - "cfg-if", - "windows-targets", -] - -[[package]] name = "libm" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.5.0", - "libc", -] - -[[package]] name = "linux-raw-sys" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1588,7 +1292,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", - "simd-adler32", ] [[package]] @@ -1687,25 +1390,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "pathfinder_geometry" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" -dependencies = [ - "log", - "pathfinder_simd", -] - -[[package]] -name = "pathfinder_simd" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebf45976c56919841273f2a0fc684c28437e2f304e264557d9c72be5d5a718be" -dependencies = [ - "rustc_version", -] - -[[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1718,27 +1402,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] name = "plotters" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ - "chrono", - "font-kit", - "image", - "lazy_static", "num-traits", - "pathfinder_geometry", "plotters-backend", - "plotters-bitmap", "plotters-svg", - "ttf-parser", "wasm-bindgen", "web-sys", ] @@ -1750,17 +1421,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] -name = "plotters-bitmap" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e7f6fb8302456d7c264a94dada86f76d76e1a03e2294ee86ca7da92983b0a6" -dependencies = [ - "gif", - "image", - "plotters-backend", -] - -[[package]] name = "plotters-svg" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1770,19 +1430,6 @@ dependencies = [ ] [[package]] -name = "png" -version = "0.17.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] name = "pretty_env_logger" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1905,17 +1552,6 @@ dependencies = [ ] [[package]] -name = "redox_users" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - -[[package]] name = "regalloc2" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2049,15 +1685,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] name = "rustix" version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2261,12 +1888,6 @@ dependencies = [ ] [[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] name = "simdutf8" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2610,12 +2231,6 @@ dependencies = [ ] [[package]] -name = "ttf-parser" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" - -[[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3112,12 +2727,6 @@ dependencies = [ ] [[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - -[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3149,15 +2758,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets", -] - -[[package]] name = "windows-sys" version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3292,15 +2892,6 @@ dependencies = [ ] [[package]] -name = "wio" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" -dependencies = [ - "winapi", -] - -[[package]] name = "wyz" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3327,18 +2918,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" [[package]] -name = "yeslogic-fontconfig-sys" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb6b23999a8b1a997bf47c7bb4d19ad4029c3327bb3386ebe0a5ff584b33c7a" -dependencies = [ - "cstr", - "dlib", - "once_cell", - "pkg-config", -] - -[[package]] name = "zerocopy" version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4,7 +4,7 @@ default-members=[".", "crates/tinywasm", "crates/types", "crates/parser"] resolver="2" [profile.wasm] -opt-level="s" +opt-level=3 lto="thin" codegen-units=1 panic="abort" diff --git a/benchmarks/benches/argon2id.rs b/benchmarks/benches/argon2id.rs index e458983..76e1eee 100644 --- a/benchmarks/benches/argon2id.rs +++ b/benchmarks/benches/argon2id.rs @@ -35,7 +35,7 @@ fn run_native(params: (i32, i32, i32)) { run_native(params.0, params.1, params.2) } -const ARGON2ID: &[u8] = include_bytes!("../../examples/rust/out/argon2id.wasm"); +static ARGON2ID: &[u8] = include_bytes!("../../examples/rust/out/argon2id.opt.wasm"); fn criterion_benchmark(c: &mut Criterion) { let params = (1000, 2, 1); diff --git a/benchmarks/benches/fibonacci.rs b/benchmarks/benches/fibonacci.rs index 61b9a68..e610ab2 100644 --- a/benchmarks/benches/fibonacci.rs +++ b/benchmarks/benches/fibonacci.rs @@ -44,7 +44,7 @@ fn run_native_recursive(n: i32) -> i32 { run_native_recursive(n - 1) + run_native_recursive(n - 2) } -const FIBONACCI: &[u8] = include_bytes!("../../examples/rust/out/fibonacci.wasm"); +static FIBONACCI: &[u8] = include_bytes!("../../examples/rust/out/fibonacci.opt.wasm"); fn criterion_benchmark(c: &mut Criterion) { // { // let mut group = c.benchmark_group("fibonacci"); @@ -58,7 +58,9 @@ fn criterion_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("fibonacci-recursive"); group.measurement_time(std::time::Duration::from_secs(5)); // group.bench_function("native", |b| b.iter(|| run_native_recursive(black_box(26)))); - group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(FIBONACCI, black_box(26), "fibonacci_recursive"))); + group.bench_function("tinywasm", |b| { + b.iter(|| run_tinywasm(black_box(FIBONACCI), black_box(26), "fibonacci_recursive")) + }); // group.bench_function("wasmi", |b| b.iter(|| run_wasmi(FIBONACCI, black_box(26), "fibonacci_recursive"))); // group.bench_function("wasmer", |b| b.iter(|| run_wasmer(FIBONACCI, black_box(26), "fibonacci_recursive"))); } diff --git a/benchmarks/benches/selfhosted.rs b/benchmarks/benches/selfhosted.rs index 441923b..adac85a 100644 --- a/benchmarks/benches/selfhosted.rs +++ b/benchmarks/benches/selfhosted.rs @@ -50,21 +50,21 @@ fn run_wasmer(wasm: &[u8]) { hello.call(&mut store, &[]).expect("call"); } -const TINYWASM: &[u8] = include_bytes!("../../examples/rust/out/tinywasm.wasm"); +static TINYWASM: &[u8] = include_bytes!("../../examples/rust/out/tinywasm.opt.wasm"); fn criterion_benchmark(c: &mut Criterion) { { - let mut group = c.benchmark_group("selfhosted-parse"); - group.bench_function("tinywasm", |b| { - b.iter(|| tinywasm::Module::parse_bytes(black_box(TINYWASM)).expect("parse")) - }); + let group = c.benchmark_group("selfhosted-parse"); + // group.bench_function("tinywasm", |b| { + // b.iter(|| tinywasm::Module::parse_bytes(black_box(TINYWASM)).expect("parse")) + // }); } { - // let mut group = c.benchmark_group("selfhosted"); + let mut group = c.benchmark_group("selfhosted"); // group.bench_function("native", |b| b.iter(run_native)); - // group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(TINYWASM))); - // group.bench_function("wasmi", |b| b.iter(|| run_wasmi(TINYWASM))); - // group.bench_function("wasmer", |b| b.iter(|| run_wasmer(TINYWASM))); + group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(black_box(TINYWASM)))); + // group.bench_function("wasmi", |b| b.iter(|| run_wasmi(black_box(TINYWASM)))); + // group.bench_function("wasmer", |b| b.iter(|| run_wasmer(black_box(TINYWASM)))); } } diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs index bddd01d..c9176a4 100644 --- a/crates/parser/src/visit.rs +++ b/crates/parser/src/visit.rs @@ -126,9 +126,7 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder { visit_global_set, Instruction::GlobalSet, u32, visit_i32_const, Instruction::I32Const, i32, visit_i64_const, Instruction::I64Const, i64, - visit_call, Instruction::Call, u32, - visit_local_set, Instruction::LocalSet, u32, - visit_local_tee, Instruction::LocalTee, u32 + visit_call, Instruction::Call, u32 } define_primitive_operands! { @@ -319,10 +317,19 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder { } match self.instructions[self.instructions.len() - 2..] { + [_, Instruction::LocalGet2(a, b)] => { + self.instructions.pop(); + self.instructions.push(Instruction::I32StoreLocal { + local_a: a, + local_b: b, + offset: arg.offset as u32, + mem_addr: arg.mem_addr as u8, + }) + } [Instruction::LocalGet(a), Instruction::I32Const(b)] => { self.instructions.pop(); self.instructions.pop(); - self.instructions.push(Instruction::I32StoreLocal { + self.instructions.push(Instruction::I32ConstStoreLocal { local: a, const_i32: b, offset: arg.offset as u32, @@ -334,10 +341,10 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder { } fn visit_local_get(&mut self, idx: u32) -> Self::Output { - if self.instructions.is_empty() { + let Some(instruction) = self.instructions.last_mut() else { return self.instructions.push(Instruction::LocalGet(idx)); - } - let instruction = self.instructions.last_mut().unwrap(); + }; + match instruction { Instruction::LocalGet(a) => *instruction = Instruction::LocalGet2(*a, idx), Instruction::LocalGet2(a, b) => *instruction = Instruction::LocalGet3(*a, *b, idx), @@ -346,32 +353,47 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder { }; } + fn visit_local_set(&mut self, idx: u32) -> Self::Output { + let Some(instruction) = self.instructions.last_mut() else { + return self.instructions.push(Instruction::LocalSet(idx)); + }; + match instruction { + Instruction::LocalGet(a) => *instruction = Instruction::LocalGetSet(*a, idx), + _ => self.instructions.push(Instruction::LocalSet(idx)), + }; + } + + fn visit_local_tee(&mut self, idx: u32) -> Self::Output { + self.instructions.push(Instruction::LocalTee(idx)) + } + fn visit_i64_rotl(&mut self) -> Self::Output { - if self.instructions.len() < 2 { + let Some([Instruction::I64Xor, Instruction::I64Const(a)]) = self.instructions.last_chunk::<2>() else { return self.instructions.push(Instruction::I64Rotl); - } - - match self.instructions[self.instructions.len() - 2..] { - [Instruction::I64Xor, Instruction::I64Const(a)] => { - self.instructions.pop(); - self.instructions.pop(); - self.instructions.push(Instruction::I64XorConstRotl(a)) - } - _ => self.instructions.push(Instruction::I64Rotl), - } + }; + let a = *a; + self.instructions.pop(); + self.instructions.pop(); + self.instructions.push(Instruction::I64XorConstRotl(a)) } fn visit_i32_add(&mut self) -> Self::Output { - if self.instructions.len() < 2 { + let Some(last) = self.instructions.last_chunk::<2>() else { return self.instructions.push(Instruction::I32Add); - } + }; - match self.instructions[self.instructions.len() - 2..] { + match *last { [Instruction::LocalGet(a), Instruction::I32Const(b)] => { self.instructions.pop(); self.instructions.pop(); self.instructions.push(Instruction::I32LocalGetConstAdd(a, b)) } + [Instruction::LocalGet2(a, b), Instruction::I32Const(c)] => { + self.instructions.pop(); + self.instructions.pop(); + self.instructions.push(Instruction::LocalGet(a)); + self.instructions.push(Instruction::I32LocalGetConstAdd(b, c)) + } _ => self.instructions.push(Instruction::I32Add), } } diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml index 78c1b42..0d2c00e 100644 --- a/crates/tinywasm/Cargo.toml +++ b/crates/tinywasm/Cargo.toml @@ -28,7 +28,7 @@ serde={version="1.0", features=["derive"]} pretty_env_logger="0.5" [features] -default=["std", "parser", "logging", "archive", "simd", "nightly"] +default=["std", "parser", "logging", "archive"] logging=["_log", "tinywasm-parser?/logging", "tinywasm-types/logging"] std=["tinywasm-parser?/std", "tinywasm-types/std"] parser=["tinywasm-parser"] diff --git a/crates/tinywasm/src/boxvec.rs b/crates/tinywasm/src/boxvec.rs index 17d3740..9c6732d 100644 --- a/crates/tinywasm/src/boxvec.rs +++ b/crates/tinywasm/src/boxvec.rs @@ -83,6 +83,18 @@ impl<T: Copy + Default> BoxVec<T> { } #[inline(always)] + pub(crate) fn extend(&mut self, iter: impl Iterator<Item = T>) { + let (lower, _) = iter.size_hint(); + let upper = lower; + let new_end = self.end + upper; + assert!(new_end <= self.data.len(), "stack overflow"); + for (i, value) in iter.enumerate() { + self.data[self.end + i] = value; + } + self.end = new_end; + } + + #[inline(always)] pub(crate) fn drain(&mut self, range: impl RangeBounds<usize>) -> Cow<'_, [T]> { let start = match range.start_bound() { core::ops::Bound::Included(&start) => start, diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index abc2819..d9e038a 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -133,40 +133,45 @@ impl ModuleInstance { &self.0.func_addrs } + #[cold] + fn not_found_error(name: &str) -> Error { + Error::Other(format!("address for {} not found", name)) + } + // resolve a function address to the global store address #[inline(always)] - pub(crate) fn resolve_func_addr(&self, addr: FuncAddr) -> FuncAddr { - self.0.func_addrs[addr as usize] + pub(crate) fn resolve_func_addr(&self, addr: FuncAddr) -> Result<FuncAddr> { + self.0.func_addrs.get(addr as usize).ok_or_else(|| Self::not_found_error("function")).copied() } // resolve a table address to the global store address #[inline(always)] - pub(crate) fn resolve_table_addr(&self, addr: TableAddr) -> TableAddr { - self.0.table_addrs[addr as usize] + pub(crate) fn resolve_table_addr(&self, addr: TableAddr) -> Result<TableAddr> { + self.0.table_addrs.get(addr as usize).ok_or_else(|| Self::not_found_error("table")).copied() } // resolve a memory address to the global store address #[inline(always)] - pub(crate) fn resolve_mem_addr(&self, addr: MemAddr) -> MemAddr { - self.0.mem_addrs[addr as usize] + pub(crate) fn resolve_mem_addr(&self, addr: MemAddr) -> Result<MemAddr> { + self.0.mem_addrs.get(addr as usize).ok_or_else(|| Self::not_found_error("mem")).copied() } // resolve a data address to the global store address #[inline(always)] - pub(crate) fn resolve_data_addr(&self, addr: DataAddr) -> MemAddr { - self.0.data_addrs[addr as usize] + pub(crate) fn resolve_data_addr(&self, addr: DataAddr) -> Result<DataAddr> { + self.0.data_addrs.get(addr as usize).ok_or_else(|| Self::not_found_error("data")).copied() } // resolve a memory address to the global store address #[inline(always)] - pub(crate) fn resolve_elem_addr(&self, addr: ElemAddr) -> ElemAddr { - self.0.elem_addrs[addr as usize] + pub(crate) fn resolve_elem_addr(&self, addr: ElemAddr) -> Result<ElemAddr> { + self.0.elem_addrs.get(addr as usize).ok_or_else(|| Self::not_found_error("elem")).copied() } // resolve a global address to the global store address #[inline(always)] - pub(crate) fn resolve_global_addr(&self, addr: GlobalAddr) -> GlobalAddr { - self.0.global_addrs[addr as usize] + pub(crate) fn resolve_global_addr(&self, addr: GlobalAddr) -> Result<GlobalAddr> { + self.0.global_addrs.get(addr as usize).ok_or_else(|| Self::not_found_error("global")).copied() } /// Get an exported function by name @@ -218,13 +223,13 @@ impl ModuleInstance { /// Get a memory by address pub fn memory<'a>(&self, store: &'a mut Store, addr: MemAddr) -> Result<MemoryRef<'a>> { - let mem = store.get_mem(self.resolve_mem_addr(addr))?; + let mem = store.get_mem(self.resolve_mem_addr(addr)?)?; Ok(MemoryRef { instance: mem.borrow() }) } /// Get a memory by address (mutable) pub fn memory_mut<'a>(&self, store: &'a mut Store, addr: MemAddr) -> Result<MemoryRefMut<'a>> { - let mem = store.get_mem(self.resolve_mem_addr(addr))?; + let mem = store.get_mem(self.resolve_mem_addr(addr)?)?; Ok(MemoryRefMut { instance: mem.borrow_mut() }) } diff --git a/crates/tinywasm/src/runtime/interpreter/macros.rs b/crates/tinywasm/src/runtime/interpreter/macros.rs index aca2252..b2042c2 100644 --- a/crates/tinywasm/src/runtime/interpreter/macros.rs +++ b/crates/tinywasm/src/runtime/interpreter/macros.rs @@ -1,20 +1,14 @@ -//! More generic macros for various instructions -//! -//! These macros are used to generate the actual instruction implementations. -//! In some basic tests this generated better assembly than using generic functions, even when inlined. -//! (Something to revisit in the future) - // Break to a block at the given index (relative to the current frame) // If there is no block at the given index, return or call the parent function // // This is a bit hard to see from the spec, but it's vaild to use breaks to return // from a function, so we need to check if the label stack is empty macro_rules! break_to { - ($break_to_relative:expr, $self:expr) => {{ + ($break_to_relative:expr, $self:expr) => { if $self.cf.break_to($break_to_relative, &mut $self.stack.values, &mut $self.stack.blocks).is_none() { return $self.exec_return(); } - }}; + }; } /// Doing the actual conversion from float to int is a bit tricky, because @@ -51,20 +45,19 @@ macro_rules! checked_conv_float { checked_conv_float!($from, $to, $to, $self) }; // Conversion with an intermediate unsigned type and error checking (three types) - ($from:tt, $intermediate:tt, $to:tt, $self:expr) => {{ - let (min, max) = float_min_max!($from, $intermediate); - let a: $from = $self.stack.values.pop()?.into(); - - if unlikely(a.is_nan()) { - return Err(Error::Trap(crate::Trap::InvalidConversionToInt)); - } - - if unlikely(a <= min || a >= max) { - return Err(Error::Trap(crate::Trap::IntegerOverflow)); - } - - $self.stack.values.push((a as $intermediate as $to).into()); - }}; + ($from:tt, $intermediate:tt, $to:tt, $self:expr) => { + $self.stack.values.replace_top_trap(|v| { + let (min, max) = float_min_max!($from, $intermediate); + let a: $from = v.into(); + if unlikely(a.is_nan()) { + return Err(Error::Trap(crate::Trap::InvalidConversionToInt)); + } + if unlikely(a <= min || a >= max) { + return Err(Error::Trap(crate::Trap::IntegerOverflow)); + } + Ok((a as $intermediate as $to).into()) + })? + }; } /// Compare two values on the stack @@ -79,9 +72,7 @@ macro_rules! comp { /// Compare a value on the stack to zero macro_rules! comp_zero { ($op:tt, $ty:ty, $self:expr) => { - $self.stack.values.replace_top(|v| { - ((<$ty>::from(v) $op 0) as i32).into() - })? + $self.stack.values.replace_top(|v| ((<$ty>::from(v) $op 0) as i32).into())? }; } diff --git a/crates/tinywasm/src/runtime/interpreter/mod.rs b/crates/tinywasm/src/runtime/interpreter/mod.rs index 6163f1b..8902aad 100644 --- a/crates/tinywasm/src/runtime/interpreter/mod.rs +++ b/crates/tinywasm/src/runtime/interpreter/mod.rs @@ -2,11 +2,10 @@ use alloc::{format, rc::Rc, string::ToString}; use core::ops::{BitAnd, BitOr, BitXor, ControlFlow, Neg}; use tinywasm_types::{BlockArgs, ElementKind, Instruction, ModuleInstanceAddr, ValType, WasmFunction}; -use super::raw::ToMemBytes; use super::stack::{BlockFrame, BlockType}; use super::{InterpreterRuntime, RawWasmValue, Stack}; use crate::runtime::CallFrame; -use crate::{cold, unlikely, Error, FuncContext, MemLoadable, ModuleInstance, Result, Store, Trap}; +use crate::{cold, unlikely, Error, FuncContext, MemLoadable, MemStorable, ModuleInstance, Result, Store, Trap}; mod macros; mod traits; @@ -36,10 +35,11 @@ struct Executor<'store, 'stack> { impl<'store, 'stack> Executor<'store, 'stack> { pub(crate) fn new(store: &'store mut Store, stack: &'stack mut Stack) -> Result<Self> { let current_frame = stack.call_stack.pop().ok_or_else(|| Error::CallStackUnderflow)?; - let current_module = store.get_module_instance_raw(current_frame.module_addr); + let current_module = store.get_module_instance_raw(current_frame.module_addr()); Ok(Self { cf: current_frame, module: current_module, stack, store }) } + #[inline] pub(crate) fn run_to_completion(&mut self) -> Result<()> { loop { match self.exec_next()? { @@ -58,16 +58,17 @@ impl<'store, 'stack> Executor<'store, 'stack> { Drop => self.exec_drop()?, Select(_valtype) => self.exec_select()?, - Call(v) => return self.exec_call_direct(*v), - CallIndirect(ty, table) => return self.exec_call_indirect(*ty, *table), + Call(v) => self.exec_call_direct(*v)?, + CallIndirect(ty, table) => self.exec_call_indirect(*ty, *table)?, - If(args, el, end) => return self.exec_if((*args).into(), *el, *end), + If(args, el, end) => self.exec_if((*args).into(), *el, *end)?, Else(end_offset) => self.exec_else(*end_offset)?, - Loop(args, end) => self.enter_block(self.cf.instr_ptr, *end, BlockType::Loop, *args), - Block(args, end) => self.enter_block(self.cf.instr_ptr, *end, BlockType::Block, *args), + Loop(args, end) => self.enter_block(self.cf.instr_ptr(), *end, BlockType::Loop, *args), + Block(args, end) => self.enter_block(self.cf.instr_ptr(), *end, BlockType::Block, *args), Br(v) => return self.exec_br(*v), BrIf(v) => return self.exec_br_if(*v), BrTable(default, len) => return self.exec_brtable(*default, *len), + BrLabel(_) => {} Return => return self.exec_return(), EndBlockFrame => self.exec_end_block()?, @@ -292,13 +293,11 @@ impl<'store, 'stack> Executor<'store, 'stack> { LocalGetSet(a, b) => self.exec_local_get_set(*a, *b), I64XorConstRotl(rotate_by) => self.exec_i64_xor_const_rotl(*rotate_by)?, I32LocalGetConstAdd(local, val) => self.exec_i32_local_get_const_add(*local, *val), - I32StoreLocal { local, const_i32, offset, mem_addr } => { - self.exec_i32_store_local(*local, *const_i32, *offset, *mem_addr)? + I32ConstStoreLocal { local, const_i32, offset, mem_addr } => { + self.exec_i32_const_store_local(*local, *const_i32, *offset, *mem_addr)? } - - i => { - cold(); - return Err(Error::UnsupportedFeature(format!("unimplemented instruction: {:?}", i))); + I32StoreLocal { local_a, local_b, offset, mem_addr } => { + self.exec_i32_store_local(*local_a, *local_b, *offset, *mem_addr)? } }; @@ -326,16 +325,17 @@ impl<'store, 'stack> Executor<'store, 'stack> { } Ok(()) } - fn exec_call(&mut self, wasm_func: Rc<WasmFunction>, owner: ModuleInstanceAddr) -> Result<ControlFlow<()>> { + fn exec_call(&mut self, wasm_func: Rc<WasmFunction>, owner: ModuleInstanceAddr) -> Result<()> { let params = self.stack.values.pop_n(wasm_func.ty.params.len())?; let new_call_frame = CallFrame::new(wasm_func, owner, params, self.stack.blocks.len() as u32); self.cf.instr_ptr += 1; // skip the call instruction self.stack.call_stack.push(core::mem::replace(&mut self.cf, new_call_frame))?; - self.module.swap_with(self.cf.module_addr, self.store); - Ok(ControlFlow::Continue(())) + self.module.swap_with(self.cf.module_addr(), self.store); + self.cf.instr_ptr -= 1; + Ok(()) } - fn exec_call_direct(&mut self, v: u32) -> Result<ControlFlow<()>> { - let func_inst = self.store.get_func(self.module.resolve_func_addr(v))?; + fn exec_call_direct(&mut self, v: u32) -> Result<()> { + let func_inst = self.store.get_func(self.module.resolve_func_addr(v)?)?; let wasm_func = match &func_inst.func { crate::Function::Wasm(wasm_func) => wasm_func, crate::Function::Host(host_func) => { @@ -343,16 +343,15 @@ impl<'store, 'stack> Executor<'store, 'stack> { let params = self.stack.values.pop_params(&host_func.ty.params)?; let res = (func.func)(FuncContext { store: self.store, module_addr: self.module.id() }, ¶ms)?; self.stack.values.extend_from_typed(&res); - self.cf.instr_ptr += 1; - return Ok(ControlFlow::Continue(())); + return Ok(()); } }; self.exec_call(wasm_func.clone(), func_inst.owner) } - fn exec_call_indirect(&mut self, type_addr: u32, table_addr: u32) -> Result<ControlFlow<()>> { + fn exec_call_indirect(&mut self, type_addr: u32, table_addr: u32) -> Result<()> { // verify that the table is of the right type, this should be validated by the parser already let func_ref = { - let table = self.store.get_table(self.module.resolve_table_addr(table_addr))?; + let table = self.store.get_table(self.module.resolve_table_addr(table_addr)?)?; let table_idx: u32 = self.stack.values.pop()?.into(); let table = table.borrow(); assert!(table.kind.element_type == ValType::RefFunc, "table is not of type funcref"); @@ -379,8 +378,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { let params = self.stack.values.pop_params(&host_func.ty.params)?; let res = (host_func.func)(FuncContext { store: self.store, module_addr: self.module.id() }, ¶ms)?; self.stack.values.extend_from_typed(&res); - self.cf.instr_ptr += 1; - return Ok(ControlFlow::Continue(())); + return Ok(()); } }; @@ -392,29 +390,27 @@ impl<'store, 'stack> Executor<'store, 'stack> { Err(Trap::IndirectCallTypeMismatch { actual: wasm_func.ty.clone(), expected: call_ty.clone() }.into()) } - fn exec_if(&mut self, args: BlockArgs, else_offset: u32, end_offset: u32) -> Result<ControlFlow<()>> { + fn exec_if(&mut self, args: BlockArgs, else_offset: u32, end_offset: u32) -> Result<()> { // truthy value is on the top of the stack, so enter the then block if i32::from(self.stack.values.pop()?) != 0 { - self.enter_block(self.cf.instr_ptr, end_offset, BlockType::If, args); - self.cf.instr_ptr += 1; - return Ok(ControlFlow::Continue(())); + self.enter_block(self.cf.instr_ptr(), end_offset, BlockType::If, args); + return Ok(()); } // falsy value is on the top of the stack if else_offset == 0 { - self.cf.instr_ptr += end_offset as usize + 1; - return Ok(ControlFlow::Continue(())); + *self.cf.instr_ptr_mut() += end_offset as usize; + return Ok(()); } - let old = self.cf.instr_ptr; - self.cf.instr_ptr += else_offset as usize; + let old = self.cf.instr_ptr(); + *self.cf.instr_ptr_mut() += else_offset as usize; self.enter_block(old + else_offset as usize, end_offset - else_offset, BlockType::Else, args); - self.cf.instr_ptr += 1; - Ok(ControlFlow::Continue(())) + Ok(()) } fn exec_else(&mut self, end_offset: u32) -> Result<()> { self.exec_end_block()?; - self.cf.instr_ptr += end_offset as usize; + *self.cf.instr_ptr_mut() += end_offset as usize; Ok(()) } fn enter_block(&mut self, instr_ptr: usize, end_instr_offset: u32, ty: BlockType, args: BlockArgs) { @@ -472,7 +468,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { } fn exec_br(&mut self, to: u32) -> Result<ControlFlow<()>> { break_to!(to, self); - self.cf.instr_ptr += 1; + self.cf.incr_instr_ptr(); Ok(ControlFlow::Continue(())) } fn exec_br_if(&mut self, to: u32) -> Result<ControlFlow<()>> { @@ -480,11 +476,11 @@ impl<'store, 'stack> Executor<'store, 'stack> { if val != 0 { break_to!(to, self); } - self.cf.instr_ptr += 1; + self.cf.incr_instr_ptr(); Ok(ControlFlow::Continue(())) } fn exec_brtable(&mut self, default: u32, len: u32) -> Result<ControlFlow<()>> { - let start = self.cf.instr_ptr + 1; + let start = self.cf.instr_ptr() + 1; let end = start + len as usize; if end > self.cf.instructions().len() { return Err(Error::Other(format!("br_table out of bounds: {} >= {}", end, self.cf.instructions().len()))); @@ -497,21 +493,21 @@ impl<'store, 'stack> Executor<'store, 'stack> { _ => return Err(Error::Other("br_table with invalid label".to_string())), } - self.cf.instr_ptr += 1; + self.cf.incr_instr_ptr(); Ok(ControlFlow::Continue(())) } fn exec_return(&mut self) -> Result<ControlFlow<()>> { - let old = self.cf.block_ptr; + let old = self.cf.block_ptr(); match self.stack.call_stack.pop() { None => return Ok(ControlFlow::Break(())), Some(cf) => self.cf = cf, } - if old > self.cf.block_ptr { + if old > self.cf.block_ptr() { self.stack.blocks.truncate(old); } - self.module.swap_with(self.cf.module_addr, self.store); + self.module.swap_with(self.cf.module_addr(), self.store); Ok(ControlFlow::Continue(())) } fn exec_end_block(&mut self) -> Result<()> { @@ -532,11 +528,11 @@ impl<'store, 'stack> Executor<'store, 'stack> { self.stack.values.last().map(|val| self.cf.set_local(local_index, *val)) } fn exec_global_get(&mut self, global_index: u32) -> Result<()> { - self.stack.values.push(self.store.get_global_val(self.module.resolve_global_addr(global_index))?); + self.stack.values.push(self.store.get_global_val(self.module.resolve_global_addr(global_index)?)?); Ok(()) } fn exec_global_set(&mut self, global_index: u32) -> Result<()> { - self.store.set_global_val(self.module.resolve_global_addr(global_index), self.stack.values.pop()?) + self.store.set_global_val(self.module.resolve_global_addr(global_index)?, self.stack.values.pop()?) } fn exec_const(&mut self, val: impl Into<RawWasmValue>) { @@ -551,7 +547,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { return Err(Error::UnsupportedFeature("memory.size with byte != 0".to_string())); } - let mem = self.store.get_mem(self.module.resolve_mem_addr(addr))?; + let mem = self.store.get_mem(self.module.resolve_mem_addr(addr)?)?; self.stack.values.push((mem.borrow().page_count() as i32).into()); Ok(()) } @@ -560,7 +556,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { return Err(Error::UnsupportedFeature("memory.grow with byte != 0".to_string())); } - let mut mem = self.store.get_mem(self.module.resolve_mem_addr(addr))?.borrow_mut(); + let mut mem = self.store.get_mem(self.module.resolve_mem_addr(addr)?)?.borrow_mut(); let prev_size = mem.page_count() as i32; let pages_delta = self.stack.values.last_mut()?; *pages_delta = match mem.grow(i32::from(*pages_delta)) { @@ -577,13 +573,13 @@ impl<'store, 'stack> Executor<'store, 'stack> { let dst: i32 = self.stack.values.pop()?.into(); if from == to { - let mut mem_from = self.store.get_mem(self.module.resolve_mem_addr(from))?.borrow_mut(); + let mut mem_from = self.store.get_mem(self.module.resolve_mem_addr(from)?)?.borrow_mut(); // copy within the same memory mem_from.copy_within(dst as usize, src as usize, size as usize)?; } else { // copy between two memories - let mem_from = self.store.get_mem(self.module.resolve_mem_addr(from))?.borrow(); - let mut mem_to = self.store.get_mem(self.module.resolve_mem_addr(to))?.borrow_mut(); + let mem_from = self.store.get_mem(self.module.resolve_mem_addr(from)?)?.borrow(); + let mut mem_to = self.store.get_mem(self.module.resolve_mem_addr(to)?)?.borrow_mut(); mem_to.copy_from_slice(dst as usize, mem_from.load(src as usize, size as usize)?)?; } Ok(()) @@ -593,7 +589,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { let val: i32 = self.stack.values.pop()?.into(); let dst: i32 = self.stack.values.pop()?.into(); - let mem = self.store.get_mem(self.module.resolve_mem_addr(addr))?; + let mem = self.store.get_mem(self.module.resolve_mem_addr(addr)?)?; mem.borrow_mut().fill(dst as usize, size as usize, val as u8)?; Ok(()) } @@ -602,8 +598,8 @@ impl<'store, 'stack> Executor<'store, 'stack> { let offset: i32 = self.stack.values.pop()?.into(); // s let dst: i32 = self.stack.values.pop()?.into(); // d - let data = self.store.get_data(self.module.resolve_data_addr(data_index))?; - let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_index))?; + let data = self.store.get_data(self.module.resolve_data_addr(data_index)?)?; + let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_index)?)?; let data_len = data.data.as_ref().map(|d| d.len()).unwrap_or(0); @@ -624,10 +620,10 @@ impl<'store, 'stack> Executor<'store, 'stack> { Ok(()) } fn exec_data_drop(&mut self, data_index: u32) -> Result<()> { - self.store.get_data_mut(self.module.resolve_data_addr(data_index)).map(|d| d.drop()) + self.store.get_data_mut(self.module.resolve_data_addr(data_index)?).map(|d| d.drop()) } fn exec_elem_drop(&mut self, elem_index: u32) -> Result<()> { - self.store.get_elem_mut(self.module.resolve_elem_addr(elem_index)).map(|e| e.drop()) + self.store.get_elem_mut(self.module.resolve_elem_addr(elem_index)?).map(|e| e.drop()) } fn exec_table_copy(&mut self, from: u32, to: u32) -> Result<()> { let size: i32 = self.stack.values.pop()?.into(); @@ -635,13 +631,13 @@ impl<'store, 'stack> Executor<'store, 'stack> { let dst: i32 = self.stack.values.pop()?.into(); if from == to { - let mut table_from = self.store.get_table(self.module.resolve_table_addr(from))?.borrow_mut(); + let mut table_from = self.store.get_table(self.module.resolve_table_addr(from)?)?.borrow_mut(); // copy within the same memory table_from.copy_within(dst as usize, src as usize, size as usize)?; } else { // copy between two memories - let table_from = self.store.get_table(self.module.resolve_table_addr(from))?.borrow(); - let mut table_to = self.store.get_table(self.module.resolve_table_addr(to))?.borrow_mut(); + let table_from = self.store.get_table(self.module.resolve_table_addr(from)?)?.borrow(); + let mut table_to = self.store.get_table(self.module.resolve_table_addr(to)?)?.borrow_mut(); table_to.copy_from_slice(dst as usize, table_from.load(src as usize, size as usize)?)?; } Ok(()) @@ -653,9 +649,10 @@ impl<'store, 'stack> Executor<'store, 'stack> { mem_addr: tinywasm_types::MemAddr, offset: u64, ) -> Result<()> { - let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr))?; + let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr)?)?; let val: u64 = self.stack.values.pop()?.into(); let Some(Ok(addr)) = offset.checked_add(val).map(|a| a.try_into()) else { + cold(); return Err(Error::Trap(crate::Trap::MemoryOutOfBounds { offset: offset as usize, len: LOAD_SIZE, @@ -667,12 +664,12 @@ impl<'store, 'stack> Executor<'store, 'stack> { self.stack.values.push(cast(val).into()); Ok(()) } - fn exec_mem_store<T: From<RawWasmValue> + ToMemBytes<N>, const N: usize>( + fn exec_mem_store<T: From<RawWasmValue> + MemStorable<N>, const N: usize>( &mut self, mem_addr: tinywasm_types::MemAddr, offset: u64, ) -> Result<()> { - let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr))?; + let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr)?)?; let val: T = self.stack.values.pop()?.into(); let val = val.to_mem_bytes(); let addr: u64 = self.stack.values.pop()?.into(); @@ -681,14 +678,14 @@ impl<'store, 'stack> Executor<'store, 'stack> { } fn exec_table_get(&mut self, table_index: u32) -> Result<()> { - let table = self.store.get_table(self.module.resolve_table_addr(table_index))?; + let table = self.store.get_table(self.module.resolve_table_addr(table_index)?)?; let idx: u32 = self.stack.values.pop()?.into(); let v = table.borrow().get_wasm_val(idx)?; self.stack.values.push(v.into()); Ok(()) } fn exec_table_set(&mut self, table_index: u32) -> Result<()> { - let table = self.store.get_table(self.module.resolve_table_addr(table_index))?; + let table = self.store.get_table(self.module.resolve_table_addr(table_index)?)?; let val = self.stack.values.pop()?.as_reference(); let idx = self.stack.values.pop()?.into(); table.borrow_mut().set(idx, val.into())?; @@ -696,14 +693,14 @@ impl<'store, 'stack> Executor<'store, 'stack> { Ok(()) } fn exec_table_size(&mut self, table_index: u32) -> Result<()> { - let table = self.store.get_table(self.module.resolve_table_addr(table_index))?; + let table = self.store.get_table(self.module.resolve_table_addr(table_index)?)?; self.stack.values.push(table.borrow().size().into()); Ok(()) } fn exec_table_init(&mut self, elem_index: u32, table_index: u32) -> Result<()> { - let table = self.store.get_table(self.module.resolve_table_addr(table_index))?; + let table = self.store.get_table(self.module.resolve_table_addr(table_index)?)?; let table_len = table.borrow().size(); - let elem = self.store.get_elem(self.module.resolve_elem_addr(elem_index))?; + let elem = self.store.get_elem(self.module.resolve_elem_addr(elem_index)?)?; let elem_len = elem.items.as_ref().map(|items| items.len()).unwrap_or(0); let size: i32 = self.stack.values.pop()?.into(); // n @@ -732,7 +729,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { } // todo: this is just a placeholder, need to check the spec fn exec_table_grow(&mut self, table_index: u32) -> Result<()> { - let table = self.store.get_table(self.module.resolve_table_addr(table_index))?; + let table = self.store.get_table(self.module.resolve_table_addr(table_index)?)?; let sz = table.borrow().size(); let n: i32 = self.stack.values.pop()?.into(); @@ -746,7 +743,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { Ok(()) } fn exec_table_fill(&mut self, table_index: u32) -> Result<()> { - let table = self.store.get_table(self.module.resolve_table_addr(table_index))?; + let table = self.store.get_table(self.module.resolve_table_addr(table_index)?)?; let n: i32 = self.stack.values.pop()?.into(); let val = self.stack.values.pop()?.as_reference(); @@ -769,14 +766,21 @@ impl<'store, 'stack> Executor<'store, 'stack> { } // custom instructions - - fn exec_i32_store_local(&mut self, local: u32, const_i32: i32, offset: u32, mem_addr: u8) -> Result<()> { - let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr as u32))?; - let val = const_i32.to_le_bytes(); + fn exec_i32_const_store_local(&mut self, local: u32, const_i32: i32, offset: u32, mem_addr: u8) -> Result<()> { + let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr as u32)?)?; + let val = const_i32.to_mem_bytes(); let addr: u64 = self.cf.get_local(local).into(); mem.borrow_mut().store((offset as u64 + addr) as usize, val.len(), &val)?; Ok(()) } + fn exec_i32_store_local(&mut self, local_a: u32, local_b: u32, offset: u32, mem_addr: u8) -> Result<()> { + let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr as u32)?)?; + let addr: u64 = self.cf.get_local(local_a).into(); + let val: i32 = self.cf.get_local(local_b).into(); + let val = val.to_mem_bytes(); + mem.borrow_mut().store((offset as u64 + addr) as usize, val.len(), &val)?; + Ok(()) + } fn exec_i32_local_get_const_add(&mut self, local: u32, val: i32) { let local: i32 = self.cf.get_local(local).into(); self.stack.values.push((local + val).into()); diff --git a/crates/tinywasm/src/runtime/raw.rs b/crates/tinywasm/src/runtime/raw.rs index 877dcb1..a186fd7 100644 --- a/crates/tinywasm/src/runtime/raw.rs +++ b/crates/tinywasm/src/runtime/raw.rs @@ -15,25 +15,6 @@ impl Debug for RawWasmValue { } } -pub(crate) trait ToMemBytes<const N: usize> { - fn to_mem_bytes(self) -> [u8; N]; -} - -macro_rules! impl_to_mem_bytes { - ($( $ty:ty, $n:expr ),*) => { - $( - impl ToMemBytes<$n> for $ty { - #[inline] - fn to_mem_bytes(self) -> [u8; $n] { - self.to_ne_bytes() - } - } - )* - }; -} - -impl_to_mem_bytes! {u8, 1, u16, 2, u32, 4, u64, 8, i8, 1, i16, 2, i32, 4, i64, 8, f32, 4, f64, 8} - impl RawWasmValue { #[inline] /// Attach a type to the raw value (does not support simd values) diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index 14077a8..30957be 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -3,10 +3,11 @@ use crate::runtime::RawWasmValue; use crate::unlikely; use crate::{Result, Trap}; -use alloc::{boxed::Box, rc::Rc, vec::Vec}; +use alloc::boxed::Box; +use alloc::{rc::Rc, vec, vec::Vec}; use tinywasm_types::{Instruction, LocalAddr, ModuleInstanceAddr, WasmFunction}; -const CALL_STACK_SIZE: usize = 1024; +pub(crate) const MAX_CALL_STACK_SIZE: usize = 1024; #[derive(Debug)] pub(crate) struct CallStack { @@ -16,10 +17,7 @@ pub(crate) struct CallStack { impl CallStack { #[inline] pub(crate) fn new(initial_frame: CallFrame) -> Self { - let mut stack = Vec::new(); - stack.reserve_exact(CALL_STACK_SIZE); - stack.push(initial_frame); - Self { stack } + Self { stack: vec![initial_frame] } } #[inline(always)] @@ -29,7 +27,7 @@ impl CallStack { #[inline(always)] pub(crate) fn push(&mut self, call_frame: CallFrame) -> Result<()> { - if unlikely((self.stack.len() + 1) >= CALL_STACK_SIZE) { + if unlikely((self.stack.len() + 1) >= MAX_CALL_STACK_SIZE) { return Err(Trap::CallStackOverflow.into()); } self.stack.push(call_frame); @@ -48,6 +46,31 @@ pub(crate) struct CallFrame { impl CallFrame { #[inline(always)] + pub(crate) fn instr_ptr(&self) -> usize { + self.instr_ptr + } + + #[inline(always)] + pub(crate) fn instr_ptr_mut(&mut self) -> &mut usize { + &mut self.instr_ptr + } + + #[inline(always)] + pub(crate) fn incr_instr_ptr(&mut self) { + self.instr_ptr += 1; + } + + #[inline(always)] + pub(crate) fn module_addr(&self) -> ModuleInstanceAddr { + self.module_addr + } + + #[inline(always)] + pub(crate) fn block_ptr(&self) -> u32 { + self.block_ptr + } + + #[inline(always)] pub(crate) fn fetch_instr(&self) -> &Instruction { match self.func_instance.instructions.get(self.instr_ptr) { Some(instr) => instr, @@ -115,7 +138,7 @@ impl CallFrame { locals.into_boxed_slice() }; - Self { instr_ptr: 0, func_instance: wasm_func_inst, module_addr: owner, locals, block_ptr } + Self { instr_ptr: 0, func_instance: wasm_func_inst, module_addr: owner, block_ptr, locals } } #[inline(always)] diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index db05364..159e366 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -4,14 +4,10 @@ use tinywasm_types::{ValType, WasmValue}; use super::BlockFrame; -pub(crate) const MIN_VALUE_STACK_SIZE: usize = 1024 * 128; -// pub(crate) const MAX_VALUE_STACK_SIZE: usize = u32::MAX / 32 as usize; +pub(crate) const VALUE_STACK_SIZE: usize = 1024 * 128; #[cfg(feature = "simd")] -pub(crate) const MIN_SIMD_VALUE_STACK_SIZE: usize = 1024 * 32; - -// #[cfg(feature = "simd")] -// pub(crate) const MAX_SIMD_VALUE_STACK_SIZE: usize = u16::MAX as usize; +pub(crate) const SIMD_VALUE_STACK_SIZE: usize = 1024 * 32; #[cfg(feature = "simd")] use crate::runtime::raw_simd::RawSimdWasmValue; @@ -27,10 +23,10 @@ pub(crate) struct ValueStack { impl Default for ValueStack { fn default() -> Self { Self { - stack: BoxVec::with_capacity(MIN_VALUE_STACK_SIZE), + stack: BoxVec::with_capacity(VALUE_STACK_SIZE), #[cfg(feature = "simd")] - simd_stack: BoxVec::with_capacity(MIN_SIMD_VALUE_STACK_SIZE), + simd_stack: BoxVec::with_capacity(SIMD_VALUE_STACK_SIZE), } } } @@ -58,20 +54,17 @@ impl ValueStack { } #[inline(always)] - pub(crate) fn calculate(&mut self, func: fn(RawWasmValue, RawWasmValue) -> RawWasmValue) -> Result<()> { - if self.stack.end < 2 { - cold(); // cold in here instead of the stack makes a huge performance difference - return Err(Error::ValueStackUnderflow); - } - - assert!( - self.stack.end >= 2 && self.stack.end <= self.stack.data.len(), - "invalid stack state (should be impossible)" - ); - self.stack.data[self.stack.end - 2] = - func(self.stack.data[self.stack.end - 2], self.stack.data[self.stack.end - 1]); + pub(crate) fn replace_top_trap(&mut self, func: fn(RawWasmValue) -> Result<RawWasmValue>) -> Result<()> { + let v = self.last_mut()?; + *v = func(*v)?; + Ok(()) + } - self.stack.end -= 1; + #[inline(always)] + pub(crate) fn calculate(&mut self, func: fn(RawWasmValue, RawWasmValue) -> RawWasmValue) -> Result<()> { + let v2 = self.pop()?; + let v1 = self.last_mut()?; + *v1 = func(*v1, v2); Ok(()) } @@ -154,7 +147,7 @@ impl ValueStack { #[inline] pub(crate) fn pop_params(&mut self, types: &[ValType]) -> Result<Vec<WasmValue>> { #[cfg(not(feature = "simd"))] - return Ok(self.pop_n_rev(types.len())?.zip(types.iter()).map(|(v, ty)| v.attach_type(*ty)).collect()); + return Ok(self.pop_n(types.len())?.iter().zip(types.iter()).map(|(v, ty)| v.attach_type(*ty)).collect()); #[cfg(feature = "simd")] { diff --git a/crates/tinywasm/src/store/memory.rs b/crates/tinywasm/src/store/memory.rs index e480577..9d6cdaf 100644 --- a/crates/tinywasm/src/store/memory.rs +++ b/crates/tinywasm/src/store/memory.rs @@ -81,12 +81,11 @@ impl MemoryInstance { if end > self.data.len() { return Err(self.trap_oob(addr, SIZE)); } - let val = T::from_le_bytes(match self.data[addr..end].try_into() { + + Ok(T::from_le_bytes(match self.data[addr..end].try_into() { Ok(bytes) => bytes, Err(_) => unreachable!("checked bounds above"), - }); - - Ok(val) + })) } #[inline] @@ -99,8 +98,7 @@ impl MemoryInstance { if end > self.data.len() { return Err(self.trap_oob(addr, len)); } - - self.data[addr..end].fill(val); + self.data[addr..end].fill_with(|| val); Ok(()) } @@ -132,15 +130,13 @@ impl MemoryInstance { Ok(()) } + #[inline] pub(crate) fn grow(&mut self, pages_delta: i32) -> Option<i32> { let current_pages = self.page_count(); let new_pages = current_pages as i64 + pages_delta as i64; + debug_assert!(new_pages <= i32::MAX as i64, "page count should never be greater than i32::MAX"); - if new_pages < 0 || new_pages > MAX_PAGES as i64 { - return None; - } - - if new_pages as usize > self.max_pages() { + if new_pages < 0 || new_pages > MAX_PAGES as i64 || new_pages as usize > self.max_pages() { return None; } @@ -150,20 +146,26 @@ impl MemoryInstance { } // Zero initialize the new pages - self.data.resize(new_size, 0); + self.data.reserve_exact(new_size); + self.data.resize_with(new_size, Default::default); self.page_count = new_pages as usize; - debug_assert!(current_pages <= i32::MAX as usize, "page count should never be greater than i32::MAX"); Some(current_pages as i32) } } +/// A trait for types that can be stored in memory +pub(crate) trait MemStorable<const N: usize> { + /// Store a value in memory + fn to_mem_bytes(self) -> [u8; N]; +} + /// A trait for types that can be loaded from memory -pub(crate) trait MemLoadable<const T: usize>: Sized + Copy { +pub(crate) trait MemLoadable<const N: usize>: Sized + Copy { /// Load a value from memory - fn from_le_bytes(bytes: [u8; T]) -> Self; + fn from_le_bytes(bytes: [u8; N]) -> Self; } -macro_rules! impl_mem_loadable_for_primitive { +macro_rules! impl_mem_traits { ($($type:ty, $size:expr),*) => { $( impl MemLoadable<$size> for $type { @@ -172,13 +174,18 @@ macro_rules! impl_mem_loadable_for_primitive { <$type>::from_le_bytes(bytes) } } + + impl MemStorable<$size> for $type { + #[inline(always)] + fn to_mem_bytes(self) -> [u8; $size] { + self.to_ne_bytes() + } + } )* } } -impl_mem_loadable_for_primitive!( - u8, 1, i8, 1, u16, 2, i16, 2, u32, 4, i32, 4, f32, 4, u64, 8, i64, 8, f64, 8, u128, 16, i128, 16 -); +impl_mem_traits!(u8, 1, i8, 1, u16, 2, i16, 2, u32, 4, i32, 4, f32, 4, u64, 8, i64, 8, f64, 8, u128, 16, i128, 16); #[cfg(test)] mod memory_instance_tests { diff --git a/crates/tinywasm/src/store/mod.rs b/crates/tinywasm/src/store/mod.rs index 6617988..f72dcab 100644 --- a/crates/tinywasm/src/store/mod.rs +++ b/crates/tinywasm/src/store/mod.rs @@ -112,55 +112,55 @@ impl Store { } /// Get the function at the actual index in the store - #[inline] + #[inline(always)] pub(crate) fn get_func(&self, addr: FuncAddr) -> Result<&FunctionInstance> { self.data.funcs.get(addr as usize).ok_or_else(|| Self::not_found_error("function")) } /// Get the memory at the actual index in the store - #[inline] + #[inline(always)] pub(crate) fn get_mem(&self, addr: MemAddr) -> Result<&RefCell<MemoryInstance>> { self.data.memories.get(addr as usize).ok_or_else(|| Self::not_found_error("memory")) } /// Get the table at the actual index in the store - #[inline] + #[inline(always)] pub(crate) fn get_table(&self, addr: TableAddr) -> Result<&RefCell<TableInstance>> { self.data.tables.get(addr as usize).ok_or_else(|| Self::not_found_error("table")) } /// Get the data at the actual index in the store - #[inline] + #[inline(always)] pub(crate) fn get_data(&self, addr: DataAddr) -> Result<&DataInstance> { self.data.datas.get(addr as usize).ok_or_else(|| Self::not_found_error("data")) } /// Get the data at the actual index in the store - #[inline] + #[inline(always)] pub(crate) fn get_data_mut(&mut self, addr: DataAddr) -> Result<&mut DataInstance> { self.data.datas.get_mut(addr as usize).ok_or_else(|| Self::not_found_error("data")) } /// Get the element at the actual index in the store - #[inline] + #[inline(always)] pub(crate) fn get_elem(&self, addr: ElemAddr) -> Result<&ElementInstance> { self.data.elements.get(addr as usize).ok_or_else(|| Self::not_found_error("element")) } /// Get the element at the actual index in the store - #[inline] + #[inline(always)] pub(crate) fn get_elem_mut(&mut self, addr: ElemAddr) -> Result<&mut ElementInstance> { self.data.elements.get_mut(addr as usize).ok_or_else(|| Self::not_found_error("element")) } /// Get the global at the actual index in the store - #[inline] + #[inline(always)] pub(crate) fn get_global(&self, addr: GlobalAddr) -> Result<&GlobalInstance> { self.data.globals.get(addr as usize).ok_or_else(|| Self::not_found_error("global")) } /// Get the global at the actual index in the store - #[inline] + #[inline(always)] pub fn get_global_val(&self, addr: MemAddr) -> Result<RawWasmValue> { self.data .globals @@ -170,7 +170,7 @@ impl Store { } /// Set the global at the actual index in the store - #[inline] + #[inline(always)] pub(crate) fn set_global_val(&mut self, addr: MemAddr, value: RawWasmValue) -> Result<()> { let global = self.data.globals.get(addr as usize).ok_or_else(|| Self::not_found_error("global")); global.map(|global| global.value.set(value)) diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs index bb1f96c..f9f861e 100644 --- a/crates/types/src/instructions.rs +++ b/crates/types/src/instructions.rs @@ -85,18 +85,16 @@ pub enum ConstInstruction { #[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))] // should be kept as small as possible (16 bytes max) #[rustfmt::skip] -#[non_exhaustive] pub enum Instruction { // > Custom Instructions BrLabel(LabelAddr), // LocalGet + I32Const + I32Add - // One of the most common patterns in the Rust compiler output I32LocalGetConstAdd(LocalAddr, i32), - // LocalGet + I32Const + I32Store => I32LocalGetConstStore + I32Const - // Also common, helps us skip the stack entirely. - // Has to be followed by an I32Const instruction - I32StoreLocal { local: LocalAddr, const_i32: i32, offset: u32, mem_addr: u8 }, - // I64Xor + I64Const + I64RotL + // LocalGet + I32Const + I32Store + I32ConstStoreLocal { local: LocalAddr, const_i32: i32, offset: u32, mem_addr: u8 }, + // LocalGet + LocalGet + I32Store + I32StoreLocal { local_a: LocalAddr, local_b: LocalAddr, offset: u32, mem_addr: u8 }, + // I64Xor + I64Const + I64RotL // Commonly used by a few crypto libraries I64XorConstRotl(i64), // LocalTee + LocalGet diff --git a/examples/rust/build.sh b/examples/rust/build.sh index 9c1f77d..fcfd01c 100755 --- a/examples/rust/build.sh +++ b/examples/rust/build.sh @@ -15,7 +15,7 @@ for bin in "${bins[@]}"; do RUSTFLAGS="-C target-feature=$features -C panic=abort" cargo build --target wasm32-unknown-unknown --package rust-wasm-examples --profile=wasm --bin "$bin" cp "$out_dir/$bin.wasm" "$dest_dir/" - wasm-opt "$dest_dir/$bin.wasm" -o "$dest_dir/$bin.wasm" -O3 --enable-bulk-memory --enable-reference-types --enable-mutable-globals + wasm-opt "$dest_dir/$bin.wasm" -o "$dest_dir/$bin.opt.wasm" -O3 --enable-bulk-memory --enable-reference-types --enable-mutable-globals if [[ ! " ${exclude_wat[@]} " =~ " $bin " ]]; then wasm2wat "$dest_dir/$bin.wasm" -o "$dest_dir/$bin.wat" diff --git a/scripts/Cargo.toml b/scripts/Cargo.toml index 5217729..a1baadf 100644 --- a/scripts/Cargo.toml +++ b/scripts/Cargo.toml @@ -4,5 +4,5 @@ publish=false edition.workspace=true [dependencies] -plotters={version="0.3"} +plotters={version="0.3", default-features=false, features=["histogram", "svg_backend"]} eyre={version="0.6"} diff --git a/scripts/src/bin/generate-charts/progress.rs b/scripts/src/bin/generate-charts/progress.rs index 1ecc09c..3cc3c26 100644 --- a/scripts/src/bin/generate-charts/progress.rs +++ b/scripts/src/bin/generate-charts/progress.rs @@ -72,6 +72,5 @@ pub fn create_progress_chart(name: &str, csv_path: &Path, output_path: &Path) -> )?; root_area.present()?; - Ok(()) } |
