optimize types

This commit is contained in:
NikVolf
2017-05-04 12:16:45 +03:00
parent db90487364
commit 67d32da16f
3 changed files with 82 additions and 22 deletions
+4 -4
View File
@@ -2,7 +2,7 @@
name = "wasm-opt"
version = "0.1.0"
dependencies = [
"parity-wasm 0.3.2 (git+https://github.com/nikvolf/parity-wasm)",
"parity-wasm 0.4.0 (git+https://github.com/nikvolf/parity-wasm)",
]
[[package]]
@@ -12,12 +12,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "parity-wasm"
version = "0.3.2"
source = "git+https://github.com/nikvolf/parity-wasm#b11f34f2e5410d0773dcf32699d767d7359e4ca9"
version = "0.4.0"
source = "git+https://github.com/nikvolf/parity-wasm#5d7c7b4094c18e71c394e83a097cd634d36f74b2"
dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
"checksum parity-wasm 0.3.2 (git+https://github.com/nikvolf/parity-wasm)" = "<none>"
"checksum parity-wasm 0.4.0 (git+https://github.com/nikvolf/parity-wasm)" = "<none>"
+74 -6
View File
@@ -6,6 +6,7 @@ use parity_wasm::elements;
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
enum Symbol {
Type(usize),
Import(usize),
Global(usize),
Function(usize),
@@ -100,6 +101,19 @@ fn expand_symbols(module: &elements::Module, set: &mut HashSet<Symbol>) {
_ => {}
}
},
Import(idx) => {
let entry = &module.import_section().expect("Import section to exist").entries()[idx];
match entry.external() {
&elements::External::Function(type_idx) => {
let type_symbol = Symbol::Type(type_idx as usize);
if !stop.contains(&type_symbol) {
fringe.push(type_symbol);
}
set.insert(type_symbol);
},
_ => {}
}
},
Function(idx) => {
let body = &module.code_section().expect("Code section to exist").bodies()[idx];
let mut code_symbols = Vec::new();
@@ -110,6 +124,13 @@ fn expand_symbols(module: &elements::Module, set: &mut HashSet<Symbol>) {
}
set.insert(symbol);
}
let signature = &module.functions_section().expect("Functions section to exist").entries()[idx];
let type_symbol = Symbol::Type(signature.type_ref() as usize);
if !stop.contains(&type_symbol) {
fringe.push(type_symbol);
}
set.insert(type_symbol);
},
Global(idx) => {
let entry = &module.global_section().expect("Global section to exist").entries()[idx];
@@ -224,6 +245,18 @@ pub fn export_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut el
None
}
pub fn type_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::TypeSection> {
for section in module.sections_mut() {
match section {
&mut elements::Section::Type(ref mut sect) => {
return Some(sect);
},
_ => { }
}
}
None
}
fn main() {
let args = env::args().collect::<Vec<_>>();
@@ -278,14 +311,34 @@ fn main() {
// Keep track of referreable symbols to rewire calls/globals
let mut eliminated_funcs = Vec::new();
let mut eliminated_globals = Vec::new();
let mut eliminated_types = Vec::new();
// First iterate throgh imports
// First, iterate through types
let mut index = 0;
let mut old_index = 0;
{
loop {
if type_section(&mut module).expect("Functons section to exist").types_mut().len() == index { break; }
if stay.contains(&Symbol::Type(old_index)) {
index += 1;
} else {
type_section(&mut module).expect("Code section to exist").types_mut().remove(index);
eliminated_types.push(old_index);
println!("Eliminated type({})", old_index);
}
old_index += 1;
}
}
// Second, iterate through imports
let mut top_funcs = 0;
let mut top_globals = 0;
{
index = 0;
old_index = 0;
let imports = import_section(&mut module).expect("Import section to exist");
loop {
let mut remove = false;
@@ -324,7 +377,7 @@ fn main() {
}
}
// Senond, iterate through globals
// Third, iterate through globals
{
let globals = global_section(&mut module).expect("Global section to exist");
@@ -344,7 +397,7 @@ fn main() {
}
}
// Third, delete orphaned functions
// Forth, delete orphaned functions
index = 0;
old_index = 0;
@@ -362,7 +415,7 @@ fn main() {
old_index += 1;
}
// Forth, eliminate unused exports
// Fivth, eliminate unused exports
{
let exports = export_section(&mut module).expect("Export section to exist");
@@ -381,14 +434,29 @@ fn main() {
}
}
if eliminated_globals.len() > 0 || eliminated_funcs.len() > 0 {
// Finaly, rewire all calls and globals references to the new indices
if eliminated_globals.len() > 0 || eliminated_funcs.len() > 0 || eliminated_types.len() > 0 {
// Finaly, rewire all calls, globals references and types to the new indices
// (only if there is anything to do)
eliminated_globals.sort();
eliminated_funcs.sort();
eliminated_types.sort();
for section in module.sections_mut() {
match section {
&mut elements::Section::Function(ref mut function_section) => {
for ref mut func_signature in function_section.entries_mut() {
let totalle = eliminated_types.iter().take_while(|i| (**i as u32) < func_signature.type_ref()).count();
*func_signature.type_ref_mut() -= totalle as u32;
}
},
&mut elements::Section::Import(ref mut import_section) => {
for ref mut import_entry in import_section.entries_mut() {
if let &mut elements::External::Function(ref mut type_ref) = import_entry.external_mut() {
let totalle = eliminated_types.iter().take_while(|i| (**i as u32) < *type_ref).count();
*type_ref -= totalle as u32;
}
}
},
&mut elements::Section::Code(ref mut code_section) => {
for ref mut func_body in code_section.bodies_mut() {
update_call_index(func_body.code_mut(), &eliminated_funcs);
+4 -12
View File
@@ -12,21 +12,13 @@ pub fn call() {
}
/* This produces the following code (after injecting gas counter & optimizing)
(module
(type (;0;) (func (result i32)))
(type (;1;) (func))
(type (;2;) (func (param i32)))
(type (;3;) (func (param i32 i32 i64 i32 i32) (result i32)))
(type (;4;) (func (param i32 i32 i32 i32 i32 i32) (result i32)))
(type (;5;) (func (param i32) (result i32)))
(type (;6;) (func (param i32 i32)))
(type (;7;) (func (param i32 i32 i32 i32 i32 i32) (result i32)))
(type (;8;) (func (param i32)))
(type (;0;) (func))
(type (;1;) (func (param i32)))
(import "env" "memory" (memory (;0;) 256 256))
(import "env" "table" (table (;0;) 0 0 anyfunc))
(import "env" "gas" (func (;0;) (type 8)))
(func (;1;) (type 1)
(import "env" "gas" (func (;0;) (type 1)))
(func (;1;) (type 0)
i32.const 2
call 0
nop)