Get rid of Option in VM stack model

This commit is contained in:
Brian Carroll 2021-10-18 21:03:54 +02:00
parent b86849347a
commit 64603a480c
2 changed files with 42 additions and 46 deletions

View File

@ -38,7 +38,7 @@ pub struct CodeBuilder {
/// Our simulation model of the Wasm stack machine
/// Keeps track of where Symbol values are in the VM stack
vm_stack: Vec<Option<Symbol>>,
vm_stack: Vec<Symbol>,
}
#[allow(clippy::new_without_default)]
@ -63,7 +63,7 @@ impl CodeBuilder {
let new_len = self.vm_stack.len() - pops as usize;
self.vm_stack.truncate(new_len);
if push {
self.vm_stack.push(None);
self.vm_stack.push(Symbol::WASM_ANONYMOUS_STACK_VALUE);
}
if DEBUG_LOG {
println!("{:?} {:?}", inst, self.vm_stack);
@ -87,7 +87,8 @@ impl CodeBuilder {
}
}
self.vm_stack.truncate(min_len);
self.vm_stack.resize(len, None);
self.vm_stack
.resize(len, Symbol::WASM_ANONYMOUS_STACK_VALUE);
if DEBUG_LOG {
println!("{:?} {:?}", instructions, self.vm_stack);
}
@ -108,7 +109,7 @@ impl CodeBuilder {
}
self.vm_stack.truncate(stack_depth - pops);
if push {
self.vm_stack.push(None);
self.vm_stack.push(Symbol::WASM_ANONYMOUS_STACK_VALUE);
}
let inst = Call(function_index);
if DEBUG_LOG {
@ -154,7 +155,7 @@ impl CodeBuilder {
);
}
self.vm_stack[len - 1] = Some(sym);
self.vm_stack[len - 1] = sym;
VirtualMachineSymbolState::Pushed { pushed_at }
}
@ -169,11 +170,8 @@ impl CodeBuilder {
let offset = stack_depth - n_symbols;
for (i, sym) in symbols.iter().enumerate() {
match self.vm_stack[offset + i] {
Some(stack_symbol) if stack_symbol == *sym => {}
_ => {
return false;
}
if self.vm_stack[offset + i] != *sym {
return false;
}
}
true
@ -199,44 +197,39 @@ impl CodeBuilder {
Pushed { pushed_at } => {
let &top = self.vm_stack.last().unwrap();
match top {
Some(top_symbol) if top_symbol == symbol => {
// We're lucky, the symbol is already on top of the VM stack
// No code to generate! (This reduces code size by up to 25% in tests.)
// Just let the caller know what happened
Some(Popped { pushed_at })
}
_ => {
// Symbol is not on top of the stack. Find it.
if let Some(found_index) =
self.vm_stack.iter().rposition(|&s| s == Some(symbol))
{
// Insert a SetLocal where the value was created (this removes it from the VM stack)
self.insertions.insert(pushed_at, SetLocal(next_local_id.0));
self.vm_stack.remove(found_index);
if top == symbol {
// We're lucky, the symbol is already on top of the VM stack
// No code to generate! (This reduces code size by up to 25% in tests.)
// Just let the caller know what happened
Some(Popped { pushed_at })
} else {
// Symbol is not on top of the stack. Find it.
if let Some(found_index) = self.vm_stack.iter().rposition(|&s| s == symbol) {
// Insert a SetLocal where the value was created (this removes it from the VM stack)
self.insertions.insert(pushed_at, SetLocal(next_local_id.0));
self.vm_stack.remove(found_index);
// Insert a GetLocal at the current position
let inst = GetLocal(next_local_id.0);
if DEBUG_LOG {
println!(
"{:?} {:?} (& insert {:?} at {:?})",
inst,
self.vm_stack,
SetLocal(next_local_id.0),
pushed_at
);
}
self.code.push(inst);
self.vm_stack.push(Some(symbol));
// This Symbol is no longer stored in the VM stack, but in a local
None
} else {
panic!(
"{:?} has state {:?} but not found in VM stack",
symbol, vm_state
// Insert a GetLocal at the current position
let inst = GetLocal(next_local_id.0);
if DEBUG_LOG {
println!(
"{:?} {:?} (& insert {:?} at {:?})",
inst,
self.vm_stack,
SetLocal(next_local_id.0),
pushed_at
);
}
self.code.push(inst);
self.vm_stack.push(symbol);
// This Symbol is no longer stored in the VM stack, but in a local
None
} else {
panic!(
"{:?} has state {:?} but not found in VM stack",
symbol, vm_state
);
}
}
}
@ -259,7 +252,7 @@ impl CodeBuilder {
);
}
self.code.push(inst);
self.vm_stack.push(Some(symbol));
self.vm_stack.push(symbol);
// This symbol has been promoted to a Local
// Tell the caller it no longer has a VirtualMachineSymbolState

View File

@ -835,6 +835,9 @@ define_builtins! {
// used by the dev backend to store the pointer to where to store large return types
23 RET_POINTER: "#ret_pointer"
// used in wasm dev backend to mark values in the VM stack that have no other Symbol
24 WASM_ANONYMOUS_STACK_VALUE: "#wasm_anonymous_stack_value"
}
1 NUM: "Num" => {
0 NUM_NUM: "Num" imported // the Num.Num type alias