Skip to content

Commit

Permalink
Merge pull request #58 from fitzgen/tombstone-arena
Browse files Browse the repository at this point in the history
Tombstone arena
  • Loading branch information
alexcrichton authored Feb 19, 2019
2 parents 89d4d34 + 1fc4b36 commit 9d7122d
Show file tree
Hide file tree
Showing 18 changed files with 384 additions and 75 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ A library for performing WebAssembly transformations

[dependencies]
failure = "0.1.2"
id-arena = { version = "2.2.0", features = ['rayon'] }
id-arena = { version = "2.2.1", features = ['rayon'] }
leb128 = "0.2.3"
log = "0.4"
rayon = "1.0.3"
Expand Down
6 changes: 5 additions & 1 deletion crates/tests-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::{Once, ONCE_INIT};

pub const FEATURES: &[&str] = &["--enable-threads", "--enable-bulk-memory", "--enable-reference-types"];
pub const FEATURES: &[&str] = &[
"--enable-threads",
"--enable-bulk-memory",
"--enable-reference-types",
];

fn require_wat2wasm() {
let status = Command::new("wat2wasm")
Expand Down
7 changes: 4 additions & 3 deletions crates/tests/tests/spec-tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ fn run(wast: &Path) -> Result<(), failure::Error> {
// TODO: should get threads working
Some("threads") => return Ok(()),
// Some("threads") => &["--enable-threads"],

Some(other) => panic!("unknown wasm proposal: {}", other),
};

Expand Down Expand Up @@ -84,7 +83,8 @@ fn run(wast: &Path) -> Result<(), failure::Error> {
}
cmd => {
let wasm = fs::read(&path)?;
let mut wasm = config.parse(&wasm)
let mut wasm = config
.parse(&wasm)
.context(format!("error parsing wasm (line {})", line))?;

// If a module is supposed to be unlinkable we'll often gc out
Expand Down Expand Up @@ -113,7 +113,8 @@ fn run(wast: &Path) -> Result<(), failure::Error> {
.emit_wasm()
.context(format!("error emitting wasm (line {})", line))?;
fs::write(&path, &wasm1)?;
let wasm2 = config.parse(&wasm1)
let wasm2 = config
.parse(&wasm1)
.and_then(|m| m.emit_wasm())
.context(format!("error re-parsing wasm (line {})", line))?;
if wasm1 != wasm2 {
Expand Down
6 changes: 3 additions & 3 deletions src/function_builder.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::ir::*;
use crate::tombstone_arena::TombstoneArena;
use crate::{FunctionId, LocalFunction, Module, TypeId, ValType};
use crate::{ModuleTypes, ModuleFunctions};
use id_arena::Arena;
use crate::{ModuleFunctions, ModuleTypes};
use std::mem;
use std::ops::{Deref, DerefMut, Drop};

/// A helpful struct used for building instances of `LocalFunction`
#[derive(Default, Debug)]
pub struct FunctionBuilder {
pub(crate) arena: Arena<Expr>,
pub(crate) arena: TombstoneArena<Expr>,
}

impl FunctionBuilder {
Expand Down
3 changes: 1 addition & 2 deletions src/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,8 +526,7 @@ pub enum Expr {
},

/// ref.null
RefNull {
},
RefNull {},

/// ref.is_null
RefIsNull {
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ mod map;
mod module;
mod parse;
pub mod passes;
mod tombstone_arena;
mod ty;

pub use crate::error::{ErrorKind, Result};
pub use crate::function_builder::{FunctionBuilder, BlockBuilder};
pub use crate::function_builder::{BlockBuilder, FunctionBuilder};
pub use crate::init_expr::InitExpr;
pub use crate::ir::{Local, LocalId};
pub use crate::module::*;
Expand Down
31 changes: 21 additions & 10 deletions src/module/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use crate::emit::{Emit, EmitContext, Section};
use crate::ir::Value;
use crate::parse::IndicesToIds;
use crate::passes::Used;
use crate::tombstone_arena::{Id, Tombstone, TombstoneArena};
use crate::{InitExpr, Module, Result, ValType};
use failure::{bail, ResultExt};
use id_arena::{Arena, Id};

/// A passive element segment identifier
pub type DataId = Id<Data>;
Expand All @@ -29,6 +29,12 @@ pub struct Data {
pub value: Vec<u8>,
}

impl Tombstone for Data {
fn on_delete(&mut self) {
self.value = Vec::new();
}
}

impl Data {
/// Returns the id of this passive data segment
pub fn id(&self) -> DataId {
Expand All @@ -40,7 +46,7 @@ impl Data {
/// various instructions.
#[derive(Debug, Default)]
pub struct ModuleData {
arena: Arena<Data>,
arena: TombstoneArena<Data>,
}

impl ModuleData {
Expand All @@ -54,18 +60,25 @@ impl ModuleData {
&mut self.arena[id]
}

/// Delete a passive data segment from this module.
///
/// It is up to you to ensure that all references to the deleted segment are
/// removed, eg `memory.init` and `data.drop` expressions.
pub fn delete(&mut self, id: DataId) {
self.arena.delete(id);
}

/// Get a shared reference to this module's passive elements.
pub fn iter(&self) -> impl Iterator<Item = &Data> {
self.arena.iter().map(|(_, f)| f)
}

/// Adds a new passive data segment with the specified contents
pub fn add(&mut self, value: Vec<u8>) -> DataId {
let id = self.arena.next_id();
self.arena.alloc(Data {
passive: true,
value,
self.arena.alloc_with_id(|id| Data {
id,
value,
passive: true,
})
}

Expand Down Expand Up @@ -110,13 +123,11 @@ impl Module {
/// validation.
pub(crate) fn reserve_data(&mut self, count: u32, ids: &mut IndicesToIds) {
for _ in 0..count {
let id = self.data.arena.next_id();
self.data.arena.alloc(Data {
ids.push_data(self.data.arena.alloc_with_id(|id| Data {
id,
passive: false, // this'll get set to `true` when parsing data
value: Vec::new(),
});
ids.push_data(id);
}));
}
}

Expand Down
18 changes: 16 additions & 2 deletions src/module/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
use crate::emit::{Emit, EmitContext, Section};
use crate::ir::Value;
use crate::parse::IndicesToIds;
use crate::tombstone_arena::{Id, Tombstone, TombstoneArena};
use crate::{FunctionId, InitExpr, Module, Result, TableKind, ValType};
use failure::{bail, ResultExt};
use id_arena::{Arena, Id};

/// A passive element segment identifier
pub type ElementId = Id<Element>;
Expand All @@ -16,11 +16,17 @@ pub struct Element {
members: Vec<FunctionId>,
}

impl Tombstone for Element {
fn on_delete(&mut self) {
self.members = Vec::new();
}
}

/// All element segments of a wasm module, used to initialize `anyfunc` tables,
/// used as function pointers.
#[derive(Debug, Default)]
pub struct ModuleElements {
arena: Arena<Element>,
arena: TombstoneArena<Element>,
}

impl ModuleElements {
Expand All @@ -34,6 +40,14 @@ impl ModuleElements {
&mut self.arena[id]
}

/// Delete an elements entry from this module.
///
/// It is up to you to ensure that all references to this deleted element
/// are removed.
pub fn delete(&mut self, id: ElementId) {
self.arena.delete(id);
}

/// Get a shared reference to this module's passive elements.
pub fn iter(&self) -> impl Iterator<Item = &Element> {
self.arena.iter().map(|(_, f)| f)
Expand Down
38 changes: 19 additions & 19 deletions src/module/exports.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
//! Exported items in a wasm module.
use crate::emit::{Emit, EmitContext, Section};
use crate::map::IdHashSet;
use crate::parse::IndicesToIds;
use crate::tombstone_arena::{Id, Tombstone, TombstoneArena};
use crate::{FunctionId, GlobalId, MemoryId, Module, Result, TableId};
use id_arena::{Arena, Id};

/// The id of an export.
pub type ExportId = Id<Export>;
Expand All @@ -19,6 +18,12 @@ pub struct Export {
pub item: ExportItem,
}

impl Tombstone for Export {
fn on_delete(&mut self) {
self.name = String::new();
}
}

impl Export {
/// Returns the id of this export
pub fn id(&self) -> ExportId {
Expand All @@ -43,8 +48,7 @@ pub enum ExportItem {
#[derive(Debug, Default)]
pub struct ModuleExports {
/// The arena containing this module's exports.
arena: Arena<Export>,
blacklist: IdHashSet<Export>,
arena: TombstoneArena<Export>,
}

impl ModuleExports {
Expand All @@ -58,6 +62,11 @@ impl ModuleExports {
&mut self.arena[id]
}

/// Delete an export entry from this module.
pub fn delete(&mut self, id: ExportId) {
self.arena.delete(id);
}

/// Get a shared reference to this module's exports.
pub fn iter(&self) -> impl Iterator<Item = &Export> {
self.arena.iter().map(|(_, f)| f)
Expand All @@ -72,18 +81,10 @@ impl ModuleExports {
})
}

/// Get a shared reference to this module's root export
///
/// Exports are "root exports" by default, unless they're blacklisted with
/// the `remove_root` method.
pub fn iter_roots(&self) -> impl Iterator<Item = &Export> {
self.iter().filter(move |e| !self.blacklist.contains(&e.id))
}

/// Removes an `id` from the set of "root exports" returned from
/// `iter_roots`.
#[doc(hidden)]
#[deprecated(note = "Use `ModuleExports::delete` instead")]
pub fn remove_root(&mut self, id: ExportId) {
self.blacklist.insert(id);
self.delete(id);
}
}

Expand All @@ -105,8 +106,7 @@ impl Module {
Memory => ExportItem::Memory(ids.get_memory(entry.index)?),
Global => ExportItem::Global(ids.get_global(entry.index)?),
};
let id = self.exports.arena.next_id();
self.exports.arena.alloc(Export {
self.exports.arena.alloc_with_id(|id| Export {
id,
name: entry.field.to_string(),
item,
Expand All @@ -122,15 +122,15 @@ impl Emit for ModuleExports {
// NB: exports are always considered used. They are the roots that the
// used analysis searches out from.

let count = self.iter_roots().count();
let count = self.iter().count();
if count == 0 {
return;
}

let mut cx = cx.start_section(Section::Export);
cx.encoder.usize(count);

for export in self.iter_roots() {
for export in self.iter() {
cx.encoder.str(&export.name);
match export.item {
ExportItem::Function(id) => {
Expand Down
4 changes: 1 addition & 3 deletions src/module/functions/local_function/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,7 @@ impl<'a> FunctionContext<'a> {

pub fn add_side_effect(&mut self, value: ExprId, side_effect: ExprId) -> ExprId {
// If we can add it to an existing `WithSideEffects` expr for this value, then do that.
if let Expr::WithSideEffects(WithSideEffects { after, .. }) =
self.func.get_mut(value)
{
if let Expr::WithSideEffects(WithSideEffects { after, .. }) = self.func.get_mut(value) {
after.push(side_effect);
return value;
}
Expand Down
16 changes: 12 additions & 4 deletions src/module/functions/local_function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::ir::*;
use crate::map::{IdHashMap, IdHashSet};
use crate::parse::IndicesToIds;
use crate::passes::Used;
use crate::{FunctionId, Module, Result, TypeId, ValType, FunctionBuilder, TableKind};
use crate::{FunctionBuilder, FunctionId, Module, Result, TableKind, TypeId, ValType};
use failure::{bail, ResultExt};
use id_arena::Id;
use std::collections::BTreeMap;
Expand Down Expand Up @@ -1245,7 +1245,11 @@ fn validate_instruction(ctx: &mut FunctionContext, inst: Operator) -> Result<()>
};
let (_, value) = ctx.pop_operand_expected(Some(expected_ty))?;
let (_, index) = ctx.pop_operand_expected(Some(I32))?;
let expr = ctx.func.alloc(TableSet { table, index, value });
let expr = ctx.func.alloc(TableSet {
table,
index,
value,
});
ctx.add_to_current_frame_block(expr);
}
Operator::TableGrow { table } => {
Expand All @@ -1256,7 +1260,11 @@ fn validate_instruction(ctx: &mut FunctionContext, inst: Operator) -> Result<()>
};
let (_, value) = ctx.pop_operand_expected(Some(expected_ty))?;
let (_, amount) = ctx.pop_operand_expected(Some(I32))?;
let expr = ctx.func.alloc(TableGrow { table, amount, value });
let expr = ctx.func.alloc(TableGrow {
table,
amount,
value,
});
ctx.push_operand(Some(I32), expr);
}
Operator::TableSize { table } => {
Expand All @@ -1265,7 +1273,7 @@ fn validate_instruction(ctx: &mut FunctionContext, inst: Operator) -> Result<()>
ctx.push_operand(Some(I32), expr);
}
Operator::RefNull => {
let expr = ctx.func.alloc(RefNull { });
let expr = ctx.func.alloc(RefNull {});
ctx.push_operand(Some(Anyref), expr);
}
Operator::RefIsNull => {
Expand Down
Loading

0 comments on commit 9d7122d

Please sign in to comment.