Skip to content

Commit ca672e9

Browse files
authored
Merge pull request #1 from fitzgen/wasm-example
Add a compile-to-wasm example to keep an eye on wasm code size
2 parents 377d641 + 7c0bed8 commit ca672e9

File tree

5 files changed

+209
-0
lines changed

5 files changed

+209
-0
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ rust:
88

99
script:
1010
- cargo test
11+
- if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then ./wasm/build.sh; fi

wasm/Cargo.lock

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wasm/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "intrusive_splay_tree_wasm"
3+
version = "0.1.0"
4+
authors = ["Nick Fitzgerald <[email protected]>"]
5+
6+
[lib]
7+
crate-type = ["cdylib"]
8+
9+
[dependencies]
10+
intrusive_splay_tree = { path = ".." }
11+
12+
[profile.release]
13+
opt-level = "s"
14+
lto = true

wasm/build.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
3+
set -eux
4+
5+
cd "$(dirname $0)"
6+
7+
rustup target add wasm32-unknown-unknown --toolchain nightly
8+
9+
cargo +nightly build --release --target wasm32-unknown-unknown
10+
11+
WASM="$(pwd)/target/wasm32-unknown-unknown/release/intrusive_splay_tree_wasm.wasm"
12+
13+
if [[ -x "$(which wasm-gc)" ]]; then
14+
new_wasm="${WASM/\.wasm/.gc.wasm}"
15+
wasm-gc "$WASM" "$new_wasm"
16+
WASM="$new_wasm"
17+
fi
18+
19+
if [[ -x "$(which wasm-opt)" ]];then
20+
new_wasm="${WASM/\.wasm/.opt.wasm}"
21+
wasm-opt -Oz "$WASM" -o "$new_wasm"
22+
WASM="$new_wasm"
23+
fi
24+
25+
cd "$(dirname $WASM)"
26+
ls -1 | grep '\.wasm$' | xargs wc -c
27+
ls -1 | grep '\.wasm$' | xargs -I '{}' sh -c 'echo -n "{} gzipped is "; cat "{}" | gzip --best | wc -c'

wasm/src/lib.rs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#![no_std]
2+
#![feature(core_intrinsics, lang_items)]
3+
4+
#[macro_use]
5+
extern crate intrusive_splay_tree;
6+
7+
use core::cmp::Ordering;
8+
use core::mem;
9+
use core::ptr;
10+
11+
pub use intrusive_splay_tree::SplayTree;
12+
13+
// Need to provide a tiny `panic_fmt` lang-item implementation for `#![no_std]`.
14+
// This implementation will translate panics into traps in the resulting
15+
// WebAssembly.
16+
#[lang = "panic_fmt"]
17+
extern "C" fn panic_fmt(
18+
_args: ::core::fmt::Arguments,
19+
_file: &'static str,
20+
_line: u32
21+
) -> ! {
22+
use core::intrinsics;
23+
unsafe {
24+
intrinsics::abort();
25+
}
26+
}
27+
28+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
29+
pub struct Id(pub u32);
30+
31+
#[derive(Debug)]
32+
pub struct Monster<'a> {
33+
id: Id,
34+
health: u32,
35+
by_id_node: intrusive_splay_tree::Node<'a>,
36+
by_health_node: intrusive_splay_tree::Node<'a>,
37+
}
38+
39+
pub struct MonstersById;
40+
41+
impl_intrusive_node! {
42+
impl<'a> IntrusiveNode<'a> for MonstersById
43+
where
44+
type Elem = Monster<'a>,
45+
node = by_id_node;
46+
}
47+
48+
impl<'a> intrusive_splay_tree::TreeOrd<'a, MonstersById> for Monster<'a> {
49+
fn tree_cmp(&self, rhs: &Monster<'a>) -> Ordering {
50+
self.id.cmp(&rhs.id)
51+
}
52+
}
53+
54+
pub struct MonstersByHealth;
55+
impl_intrusive_node! {
56+
impl<'a> IntrusiveNode<'a> for MonstersByHealth
57+
where
58+
type Elem = Monster<'a>,
59+
node = by_health_node;
60+
}
61+
impl<'a> intrusive_splay_tree::TreeOrd<'a, MonstersByHealth> for Monster<'a> {
62+
fn tree_cmp(&self, rhs: &Monster<'a>) -> Ordering {
63+
self.health.cmp(&rhs.health)
64+
}
65+
}
66+
67+
impl<'a> intrusive_splay_tree::TreeOrd<'a, MonstersByHealth> for u32 {
68+
fn tree_cmp(&self, rhs: &Monster<'a>) -> Ordering {
69+
self.cmp(&rhs.health)
70+
}
71+
}
72+
73+
impl<'a> intrusive_splay_tree::TreeOrd<'a, MonstersById> for Id {
74+
fn tree_cmp(&self, rhs: &Monster<'a>) -> Ordering {
75+
self.cmp(&rhs.id)
76+
}
77+
}
78+
79+
extern "C" {
80+
fn alloc(n: usize) -> *mut u8;
81+
}
82+
83+
#[no_mangle]
84+
pub unsafe extern "C" fn new_id_tree() -> *mut SplayTree<'static, MonstersById> {
85+
let p = alloc(mem::size_of::<SplayTree<MonstersById>>());
86+
let p = p as *mut SplayTree<MonstersById>;
87+
ptr::write(p, SplayTree::default());
88+
p
89+
}
90+
91+
#[no_mangle]
92+
pub unsafe extern "C" fn new_health_tree() -> *mut SplayTree<'static, MonstersByHealth> {
93+
let p = alloc(mem::size_of::<SplayTree<MonstersByHealth>>());
94+
let p = p as *mut SplayTree<MonstersByHealth>;
95+
ptr::write(p, SplayTree::default());
96+
p
97+
}
98+
99+
#[no_mangle]
100+
pub unsafe extern "C" fn new_monster(
101+
id: u32,
102+
health: u32,
103+
by_id_tree: *mut SplayTree<'static, MonstersById>,
104+
by_health_tree: *mut SplayTree<'static, MonstersByHealth>,
105+
) -> *const Monster<'static> {
106+
let p = alloc(mem::size_of::<Monster>());
107+
let p = p as *mut Monster<'static>;
108+
ptr::write(
109+
p,
110+
Monster {
111+
id: Id(id),
112+
health,
113+
by_id_node: Default::default(),
114+
by_health_node: Default::default(),
115+
},
116+
);
117+
let monster = &*p;
118+
(*by_id_tree).insert(monster);
119+
(*by_health_tree).insert(monster);
120+
monster
121+
}
122+
123+
#[no_mangle]
124+
pub unsafe extern "C" fn query_by_id(
125+
tree: *mut SplayTree<'static, MonstersById>,
126+
id: u32,
127+
) -> *const Monster<'static> {
128+
(*tree).find(&Id(id)).map_or(ptr::null(), |m| m as *const _)
129+
}
130+
131+
#[no_mangle]
132+
pub unsafe extern "C" fn query_by_health(
133+
tree: *mut SplayTree<'static, MonstersByHealth>,
134+
health: u32,
135+
) -> *const Monster<'static> {
136+
(*tree).find(&health).map_or(ptr::null(), |m| m as *const _)
137+
}

0 commit comments

Comments
 (0)