Skip to content

Commit c25e79b

Browse files
chore: improve breaking
Signed-off-by: Henry Gressmann <[email protected]>
1 parent ee869ab commit c25e79b

File tree

7 files changed

+100
-60
lines changed

7 files changed

+100
-60
lines changed

crates/tinywasm/src/runtime/executor/mod.rs

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::{DefaultRuntime, Stack};
22
use crate::{
3+
get_label_args,
34
log::debug,
45
runtime::{BlockType, LabelFrame, RawWasmValue},
56
CallFrame, Error, ModuleInstance, Result, Store,
@@ -137,37 +138,45 @@ fn exec_one(
137138
info!("end: {:?} (@{})", instrs[end_instr_ptr], end_instr_ptr);
138139

139140
if stack.values.pop_t::<i32>()? != 0 {
140-
// let params = stack.values.pop_block_params(*args, &module)?;
141-
cf.labels.push(LabelFrame {
142-
instr_ptr: cf.instr_ptr,
143-
end_instr_ptr: cf.instr_ptr + *end_offset,
144-
stack_ptr: stack.values.len(), // - params,
145-
args: *args,
146-
ty: BlockType::If,
147-
});
141+
cf.enter_label(
142+
LabelFrame {
143+
instr_ptr: cf.instr_ptr,
144+
end_instr_ptr: cf.instr_ptr + *end_offset,
145+
stack_ptr: stack.values.len(), // - params,
146+
args: get_label_args(*args, &module)?,
147+
ty: BlockType::If,
148+
},
149+
&mut stack.values,
150+
)
148151
}
149152
}
150153

151154
Loop(args, end_offset) => {
152155
// let params = stack.values.pop_block_params(*args, &module)?;
153-
cf.labels.push(LabelFrame {
154-
instr_ptr: cf.instr_ptr,
155-
end_instr_ptr: cf.instr_ptr + *end_offset,
156-
stack_ptr: stack.values.len(), // - params,
157-
args: *args,
158-
ty: BlockType::Loop,
159-
});
156+
cf.enter_label(
157+
LabelFrame {
158+
instr_ptr: cf.instr_ptr,
159+
end_instr_ptr: cf.instr_ptr + *end_offset,
160+
stack_ptr: stack.values.len(), // - params,
161+
args: get_label_args(*args, &module)?,
162+
ty: BlockType::Loop,
163+
},
164+
&mut stack.values,
165+
);
160166
}
161167

162168
Block(args, end_offset) => {
163169
// let params = stack.values.pop_block_params(*args, &module)?;
164-
cf.labels.push(LabelFrame {
165-
instr_ptr: cf.instr_ptr,
166-
end_instr_ptr: cf.instr_ptr + *end_offset,
167-
stack_ptr: stack.values.len(), //- params,
168-
args: *args,
169-
ty: BlockType::Block,
170-
});
170+
cf.enter_label(
171+
LabelFrame {
172+
instr_ptr: cf.instr_ptr,
173+
end_instr_ptr: cf.instr_ptr + *end_offset,
174+
stack_ptr: stack.values.len(), //- params,
175+
args: get_label_args(*args, &module)?,
176+
ty: BlockType::Block,
177+
},
178+
&mut stack.values,
179+
);
171180
}
172181

173182
BrTable(_default, len) => {
@@ -186,10 +195,10 @@ fn exec_one(
186195
todo!()
187196
}
188197

189-
Br(v) => cf.break_to(*v, &mut stack.values)?,
198+
Br(v) => cf.break_to(*v, &mut stack.values, module)?,
190199
BrIf(v) => {
191200
if stack.values.pop_t::<i32>()? > 0 {
192-
cf.break_to(*v, &mut stack.values)?
201+
cf.break_to(*v, &mut stack.values, module)?
193202
};
194203
}
195204

@@ -215,12 +224,7 @@ fn exec_one(
215224
panic!("end: no label to end, this should have been validated by the parser");
216225
};
217226

218-
let res_count = match block.args {
219-
BlockArgs::Empty => 0,
220-
BlockArgs::Type(_) => 1,
221-
BlockArgs::FuncType(t) => module.func_ty(t).results.len(),
222-
};
223-
227+
let res_count = block.args.results;
224228
info!("we want to keep {} values on the stack", res_count);
225229
info!("current block stack ptr: {}", block.stack_ptr);
226230
info!("stack: {:?}", stack.values);

crates/tinywasm/src/runtime/stack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod call_stack;
33
mod value_stack;
44

55
use self::{call_stack::CallStack, value_stack::ValueStack};
6-
pub(crate) use blocks::{BlockType, LabelFrame};
6+
pub(crate) use blocks::{get_label_args, BlockType, LabelFrame};
77
pub(crate) use call_stack::CallFrame;
88

99
/// A WebAssembly Stack

crates/tinywasm/src/runtime/stack/blocks.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use alloc::vec::Vec;
22
use log::info;
33
use tinywasm_types::{BlockArgs, FuncType};
44

5+
use crate::{ModuleInstance, Result};
6+
57
#[derive(Debug, Default, Clone)]
68
pub(crate) struct Labels(Vec<LabelFrame>);
79

@@ -35,7 +37,7 @@ impl Labels {
3537

3638
/// keep the top `len` blocks and discard the rest
3739
#[inline]
38-
pub(crate) fn trim(&mut self, len: usize) {
40+
pub(crate) fn truncate(&mut self, len: usize) {
3941
self.0.truncate(len);
4042
}
4143
}
@@ -49,7 +51,7 @@ pub(crate) struct LabelFrame {
4951

5052
// position of the stack pointer when the block was entered
5153
pub(crate) stack_ptr: usize,
52-
pub(crate) args: BlockArgs,
54+
pub(crate) args: LabelArgs,
5355
pub(crate) ty: BlockType,
5456
}
5557

@@ -61,3 +63,20 @@ pub(crate) enum BlockType {
6163
Else,
6264
Block,
6365
}
66+
67+
#[derive(Debug, Clone)]
68+
pub struct LabelArgs {
69+
pub params: usize,
70+
pub results: usize,
71+
}
72+
73+
pub fn get_label_args(args: BlockArgs, module: &ModuleInstance) -> Result<LabelArgs> {
74+
Ok(match args {
75+
BlockArgs::Empty => LabelArgs { params: 0, results: 0 },
76+
BlockArgs::Type(t) => LabelArgs { params: 0, results: 1 },
77+
BlockArgs::FuncType(t) => LabelArgs {
78+
params: module.func_ty(t).params.len(),
79+
results: module.func_ty(t).results.len(),
80+
},
81+
})
82+
}

crates/tinywasm/src/runtime/stack/call_stack.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use crate::{runtime::RawWasmValue, BlockType, Error, Result};
1+
use crate::{runtime::RawWasmValue, BlockType, Error, LabelFrame, ModuleInstance, Result};
22
use alloc::{boxed::Box, vec::Vec};
33
use log::{debug, info};
4-
use tinywasm_types::{ValType, WasmValue};
4+
use tinywasm_types::{BlockArgs, ValType, WasmValue};
55

66
use super::blocks::Labels;
77

@@ -79,38 +79,50 @@ pub(crate) struct CallFrame {
7979
}
8080

8181
impl CallFrame {
82+
#[inline]
83+
/// Push a new label to the label stack and ensure the stack has the correct values
84+
pub(crate) fn enter_label(&mut self, label_frame: LabelFrame, stack: &mut super::ValueStack) {
85+
if label_frame.args.params > 0 {
86+
stack.extend_from_within((label_frame.stack_ptr - label_frame.args.params)..label_frame.stack_ptr);
87+
}
88+
89+
self.labels.push(label_frame);
90+
}
91+
8292
/// Break to a block at the given index (relative to the current frame)
8393
#[inline]
84-
pub(crate) fn break_to(&mut self, break_to_relative: u32, value_stack: &mut super::ValueStack) -> Result<()> {
94+
pub(crate) fn break_to(
95+
&mut self,
96+
break_to_relative: u32,
97+
value_stack: &mut super::ValueStack,
98+
module: &ModuleInstance,
99+
) -> Result<()> {
85100
let current_label = self.labels.top().ok_or(Error::LabelStackUnderflow)?;
86101
let break_to = self
87102
.labels
88103
.get_relative_to_top(break_to_relative as usize)
89104
.ok_or(Error::LabelStackUnderflow)?;
90105

91-
info!("current label: {:?}", current_label);
92-
info!("we're breaking to: {:?} ?", break_to);
106+
// trim the lable's stack from the stack
107+
value_stack.truncate_keep(break_to.stack_ptr, break_to.args.results);
93108

94109
// instr_ptr points to the label instruction, but the next step
95110
// will increment it by 1 since we're changing the "current" instr_ptr
96111
match break_to.ty {
97112
BlockType::Loop => {
98113
// this is a loop, so we want to jump back to the start of the loop
99114
self.instr_ptr = break_to.instr_ptr;
100-
value_stack.truncate(break_to.stack_ptr);
101115

102116
// we also want to trim the label stack to the loop (but not including the loop)
103-
self.labels.trim(self.labels.len() - break_to_relative as usize);
117+
self.labels.truncate(self.labels.len() - break_to_relative as usize);
104118
}
105119
BlockType::Block => {
106-
debug!("current instr_ptr: {}", self.instr_ptr);
107-
108-
// this is a block, so we want to jump to the next instruction after the block ends
109-
self.instr_ptr = break_to.end_instr_ptr + 1;
110-
value_stack.truncate(break_to.stack_ptr);
120+
// this is a block, so we want to jump to the next instruction after the block ends (the inst_ptr will be incremented by 1 before the next instruction is executed)
121+
self.instr_ptr = break_to.end_instr_ptr;
111122

112123
// we also want to trim the label stack, including the block
113-
self.labels.trim(self.labels.len() - break_to_relative as usize + 1);
124+
self.labels
125+
.truncate(self.labels.len() - (break_to_relative as usize + 1));
114126
}
115127
_ => unimplemented!("break to block type: {:?}", current_label.ty),
116128
}

crates/tinywasm/src/runtime/stack/value_stack.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ impl ValueStack {
3131
&self.stack
3232
}
3333

34+
#[inline]
35+
pub(crate) fn extend_from_within(&mut self, range: Range<usize>) {
36+
self.top += range.len();
37+
self.stack.extend_from_within(range);
38+
}
39+
3440
#[inline]
3541
pub(crate) fn len(&self) -> usize {
3642
assert!(self.top <= self.stack.len());

0 commit comments

Comments
 (0)