Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
342 changes: 315 additions & 27 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ members = [
"examples/doom",
"examples/quake",
"examples/hello-world",
"benches",
]

[workspace.package]
Expand Down Expand Up @@ -54,7 +55,7 @@ libc = "0.2.149"
log = "0.4.20"
object = { version = "0.36.1", default-features = false }
paste = "1.0.15"
picosimd = { version = "0.9.0", features = ["ops"] }
picosimd = { version = "0.9.2", features = ["ops"] }
proc-macro2 = "1.0.69"
proptest = "1.3.1"
quote = "1.0.33"
Expand Down
17 changes: 17 additions & 0 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "benches"
version.workspace = true
authors.workspace = true
license.workspace = true
edition.workspace = true
rust-version.workspace = true
repository.workspace = true
publish = false

[dependencies]
polkavm = { workspace = true, features = ["export-internals-for-testing"] }
criterion = "0.7.0"
oorandom = "11.1.5"

[lints]
workspace = true
3 changes: 3 additions & 0 deletions benches/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

cargo run --release -- --bench "$@"
92 changes: 92 additions & 0 deletions benches/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use polkavm::_for_testing::PageSet;
use std::hint::black_box;
use std::time::{Duration, Instant};

const SEED: u128 = 9324658635124;
const MAX: u64 = 1048576;

fn run_insert_test<const REMOVE: bool, const CHECK: bool>(b: &mut Bencher, max_range: u64) {
b.iter_custom(|iters| {
let mut elapsed = Duration::default();
for _ in 0..iters {
let mut set = PageSet::new();
let mut rng = oorandom::Rand64::new(SEED);
let start = Instant::now();
for n in 0..3000000 {
let min = rng.rand_range(0..max_range);
let max = rng.rand_range(min..max_range);
let min = min as u32;
let max = max as u32;

if (n % 3) == 0 {
set.insert((min, max));
} else if (n % 3) == 1 {
if REMOVE {
set.remove((min, max));
}
} else {
if CHECK {
black_box(set.contains((min, max)));
}
}
}
elapsed += start.elapsed();
black_box(set);
}

elapsed
});
}

fn pageset_benchmarks(c: &mut Criterion) {
c.bench_function("insert million entries (narrow range)", |b| {
run_insert_test::<false, false>(b, 4000)
});
c.bench_function("insert and remove million entries (narrow range)", |b| {
run_insert_test::<true, false>(b, 4000)
});
c.bench_function("insert million entries (wide range)", |b| run_insert_test::<false, false>(b, MAX));
c.bench_function("insert and remove million entries (wide range)", |b| {
run_insert_test::<true, false>(b, MAX)
});
c.bench_function("insert, remove and check million entries (wide range)", |b| {
run_insert_test::<true, true>(b, MAX)
});
c.bench_function("clear empty set", |b| {
b.iter_custom(|iters| {
let mut set = PageSet::new();
let start = Instant::now();
for _ in 0..iters {
set.clear();
}
let elapsed = start.elapsed();
black_box(set);
elapsed
});
});

c.bench_function("clear set with 50 thousand entries", |b| {
b.iter_custom(|iters| {
let mut elapsed = Duration::default();
for _ in 0..iters {
let mut set = PageSet::new();
let mut rng = oorandom::Rand64::new(SEED);
for _ in 0..50000 {
let min = rng.rand_range(0..MAX);
let max = rng.rand_range(min..MAX);
set.insert((min as u32, max as u32));
}

let start = Instant::now();
set.clear();
elapsed += start.elapsed();
black_box(set);
}
elapsed
});
});
}

criterion_group!(benches, pageset_benchmarks);
criterion_main!(benches);
2 changes: 1 addition & 1 deletion ci/jobs/clippy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ echo ">> cargo clippy (guests)"
cd guest-programs
cargo clippy \
-Z build-std=core,alloc \
--target "$PWD/../crates/polkavm-linker/riscv32emac-unknown-none-polkavm.json" \
--target "$PWD/../crates/polkavm-linker/targets/legacy/riscv32emac-unknown-none-polkavm.json" \
--all

cd ../..
18 changes: 1 addition & 17 deletions crates/polkavm-common/src/assembler.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::program::{Instruction, RawReg, Reg};
use crate::utils::{parse_imm, parse_immediate, parse_reg, ParsedImmediate};
use crate::utils::{parse_imm, parse_immediate, parse_reg, parse_slice, ParsedImmediate};
use alloc::borrow::ToOwned;
use alloc::collections::BTreeMap;
use alloc::format;
Expand Down Expand Up @@ -257,22 +257,6 @@ pub fn assemble(code: &str) -> Result<Vec<u8>, String> {
continue;
}

fn parse_slice(text: &str) -> Option<Vec<u8>> {
let text = text.trim().replace(' ', "");
if text.len() % 2 != 0 {
return None;
}

let mut output = Vec::new();
for chunk in text.as_bytes().chunks(2) {
let chunk = core::str::from_utf8(chunk).ok()?;
let chunk = u8::from_str_radix(chunk, 16).ok()?;
output.push(chunk);
}

Some(output)
}

if let Some(line) = line.strip_prefix("%ro_data = ") {
let Some(value) = parse_slice(line) else {
return Err(format!("cannot parse line {nth_line}"));
Expand Down
6 changes: 5 additions & 1 deletion crates/polkavm-common/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3956,7 +3956,11 @@ where
(offset, None)
} else if is_bounded {
is_done = true;
(core::cmp::min(offset + 1, code.len() as u32), Some(offset))
if offset == u32::MAX {
(u32::MAX, None)
} else {
(core::cmp::min(offset + 1, code.len() as u32), Some(offset))
}
} else {
let next_offset = find_next_offset_unbounded(bitmask, code.len() as u32, offset);
debug_assert!(
Expand Down
38 changes: 38 additions & 0 deletions crates/polkavm-common/src/simulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2897,4 +2897,42 @@ mod tests {
",
);
}

#[test]
fn test_xor_and_shift() {
assert_timeline(
test_config(),
"
a1 = a1 ^ 0xffffffffffffffff
a1 = a0 >> a1
fallthrough
",
"
DeER.. a1 = a1 ^ 0xffffffffffffffff
D=eER. a1 = a0 >> a1
.DeeER fallthrough
",
)
}

#[test]
fn test_move_reg_decode_slots() {
assert_timeline(
test_config(),
"
s0 = a1
a0 = a1
a1 = t0
a2 = s1
trap
",
"
D..... s0 = a1
D..... a0 = a1
D..... a1 = t0
D..... a2 = s1
.DeeER trap
",
)
}
}
17 changes: 17 additions & 0 deletions crates/polkavm-common/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,23 @@ pub fn parse_immediate(text: &str) -> Option<ParsedImmediate> {
}
}

#[cfg(feature = "alloc")]
pub fn parse_slice(text: &str) -> Option<Vec<u8>> {
let text = text.trim().replace(' ', "");
if text.len() % 2 != 0 {
return None;
}

let mut output = Vec::new();
for chunk in text.as_bytes().chunks(2) {
let chunk = core::str::from_utf8(chunk).ok()?;
let chunk = u8::from_str_radix(chunk, 16).ok()?;
output.push(chunk);
}

Some(output)
}

pub trait GasVisitorT: ParsingVisitor {
fn take_block_cost(&mut self) -> Option<u32>;
fn is_at_start_of_basic_block(&self) -> bool;
Expand Down
4 changes: 2 additions & 2 deletions crates/polkavm-disassembler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,9 @@ mod tests {
for format in [
DisassemblyFormat::Guest,
DisassemblyFormat::DiffFriendly,
#[cfg(target_arg = "x86_84")]
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
DisassemblyFormat::GuestAndNative,
#[cfg(target_arg = "x86_84")]
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
DisassemblyFormat::Native,
] {
assert!(!disassemble_with_gas(blob, format).is_empty());
Expand Down
Loading