Skip to content

Commit 8b67f56

Browse files
committed
Wasm translator: move stacks into FuncEnvironment.
This is a refactor that came up [here]: we currently have a split between the "environment" and the "stacks" in the Wasm translator that is *mostly* a path-dependent property from our development history: the environment used to be a trait purely with hook implementations. It turns out that carrying through the multiple bits was becoming fairly verbose plumbing and it is desired to collapse it somewhat. This PR puts `FuncTranslationStacks` under `FuncEnvironment`. As a result, all of our Wasmtime-specific state is now in one container that we can plumb through more easily. There is a tiny bit more cloning here: calls and a few other instructions were peeking a slice of the operand stack and passing that into a method on the environ (taking a mut self) to codegen certain sequences. An alternative would have been to indirect somehow -- pass a `Range<usize>` or a closure that gets the environ back to yield the args slice -- but it didn't seem worth the complexity here. Happy to change if needed. [here]: bytecodealliance#11921 (comment)
1 parent 1f2feaf commit 8b67f56

File tree

5 files changed

+1047
-998
lines changed

5 files changed

+1047
-998
lines changed

crates/cranelift/src/func_environ.rs

Lines changed: 41 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use cranelift_codegen::ir::immediates::{Imm64, Offset32, V128Imm};
1313
use cranelift_codegen::ir::pcc::Fact;
1414
use cranelift_codegen::ir::{self, BlockArg, ExceptionTableData, ExceptionTableItem, types};
1515
use cranelift_codegen::ir::{ArgumentPurpose, ConstantData, Function, InstBuilder, MemFlags};
16-
use cranelift_codegen::ir::{Block, ExceptionTag, types::*};
16+
use cranelift_codegen::ir::{Block, types::*};
1717
use cranelift_codegen::isa::{TargetFrontendConfig, TargetIsa};
1818
use cranelift_entity::packed_option::{PackedOption, ReservedValue};
1919
use cranelift_entity::{EntityRef, PrimaryMap, SecondaryMap};
@@ -105,6 +105,9 @@ pub struct FuncEnvironment<'module_environment> {
105105
needs_gc_heap: bool,
106106
entities: WasmEntities,
107107

108+
/// Translation state at the given point.
109+
pub(crate) stacks: FuncTranslationStacks,
110+
108111
#[cfg(feature = "gc")]
109112
ty_to_gc_layout: std::collections::HashMap<
110113
wasmtime_environ::ModuleInternedTypeIndex,
@@ -215,6 +218,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
215218
sig_ref_to_ty: SecondaryMap::default(),
216219
needs_gc_heap: false,
217220
entities: WasmEntities::default(),
221+
stacks: FuncTranslationStacks::new(),
218222

219223
#[cfg(feature = "gc")]
220224
ty_to_gc_layout: std::collections::HashMap::new(),
@@ -1229,7 +1233,6 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
12291233
&mut self,
12301234
validator: &FuncValidator<impl WasmModuleResources>,
12311235
builder: &mut FunctionBuilder,
1232-
stack: &mut FuncTranslationStacks,
12331236
) -> WasmResult<()> {
12341237
// Take ownership of the state-slot builder temporarily rather
12351238
// than mutably borrowing so we can invoke a method below.
@@ -1251,20 +1254,20 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
12511254
// to the instrumentation slot; or alternately, extending
12521255
// the debug instrumentation mechanism to be able to
12531256
// directly refer to the user stack-slot.
1254-
for i in stack.stack_shape.len()..stack.stack.len() {
1257+
for i in self.stacks.stack_shape.len()..self.stacks.stack.len() {
12551258
let parent_shape = i
12561259
.checked_sub(1)
1257-
.map(|parent_idx| stack.stack_shape[parent_idx]);
1260+
.map(|parent_idx| self.stacks.stack_shape[parent_idx]);
12581261
if let Some(this_ty) = validator
1259-
.get_operand_type(stack.stack.len() - i - 1)
1262+
.get_operand_type(self.stacks.stack.len() - i - 1)
12601263
.expect("Index should not be out of range")
12611264
{
12621265
let wasm_ty = self.convert_valtype(this_ty)?;
12631266
let (this_shape, offset) =
12641267
b.push_stack(parent_shape, FrameValType::from(wasm_ty));
1265-
stack.stack_shape.push(this_shape);
1268+
self.stacks.stack_shape.push(this_shape);
12661269

1267-
let value = stack.stack[i];
1270+
let value = self.stacks.stack[i];
12681271
builder.ins().stack_store(value, slot, offset.offset());
12691272
} else {
12701273
// Unreachable code with unknown type -- no
@@ -1279,14 +1282,11 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
12791282
Ok(())
12801283
}
12811284

1282-
pub(crate) fn debug_tags(
1283-
&self,
1284-
stack: &FuncTranslationStacks,
1285-
srcloc: ir::SourceLoc,
1286-
) -> Vec<ir::DebugTag> {
1285+
pub(crate) fn debug_tags(&self, srcloc: ir::SourceLoc) -> Vec<ir::DebugTag> {
12871286
if let Some((slot, _b)) = &self.state_slot {
1288-
stack.assert_debug_stack_is_synced();
1289-
let stack_shape = stack
1287+
self.stacks.assert_debug_stack_is_synced();
1288+
let stack_shape = self
1289+
.stacks
12901290
.stack_shape
12911291
.last()
12921292
.map(|s| s.raw())
@@ -1855,9 +1855,7 @@ impl FuncEnvironment<'_> {
18551855
struct Call<'a, 'func, 'module_env> {
18561856
builder: &'a mut FunctionBuilder<'func>,
18571857
env: &'a mut FuncEnvironment<'module_env>,
1858-
stack: &'a FuncTranslationStacks,
18591858
srcloc: ir::SourceLoc,
1860-
handlers: Vec<(Option<ExceptionTag>, Block)>,
18611859
tail: bool,
18621860
}
18631861

@@ -1878,17 +1876,12 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
18781876
pub fn new(
18791877
builder: &'a mut FunctionBuilder<'func>,
18801878
env: &'a mut FuncEnvironment<'module_env>,
1881-
stack: &'a FuncTranslationStacks,
18821879
srcloc: ir::SourceLoc,
1883-
handlers: impl IntoIterator<Item = (Option<ExceptionTag>, Block)>,
18841880
) -> Self {
1885-
let handlers = handlers.into_iter().collect();
18861881
Call {
18871882
builder,
18881883
env,
1889-
stack,
18901884
srcloc,
1891-
handlers,
18921885
tail: false,
18931886
}
18941887
}
@@ -1897,15 +1890,12 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
18971890
pub fn new_tail(
18981891
builder: &'a mut FunctionBuilder<'func>,
18991892
env: &'a mut FuncEnvironment<'module_env>,
1900-
stack: &'a FuncTranslationStacks,
19011893
srcloc: ir::SourceLoc,
19021894
) -> Self {
19031895
Call {
19041896
builder,
19051897
env,
1906-
stack,
19071898
srcloc,
1908-
handlers: vec![],
19091899
tail: true,
19101900
}
19111901
}
@@ -2343,7 +2333,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
23432333
&mut self,
23442334
sig: ir::SigRef,
23452335
) -> Option<(ir::ExceptionTable, Block, CallRets)> {
2346-
if self.handlers.len() > 0 {
2336+
if !self.tail && !self.env.stacks.handlers.is_empty() {
23472337
let continuation_block = self.builder.create_block();
23482338
let mut args = vec![];
23492339
let mut results = smallvec![];
@@ -2364,14 +2354,14 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
23642354
.dfg
23652355
.block_call(continuation_block, args.iter());
23662356
let mut handlers = vec![ExceptionTableItem::Context(self.caller_vmctx())];
2367-
for (tag, block) in &self.handlers {
2357+
for (tag, block) in self.env.stacks.handlers.handlers() {
23682358
let block_call = self
23692359
.builder
23702360
.func
23712361
.dfg
2372-
.block_call(*block, &[BlockArg::TryCallExn(0)]);
2362+
.block_call(block, &[BlockArg::TryCallExn(0)]);
23732363
handlers.push(match tag {
2374-
Some(tag) => ExceptionTableItem::Tag(*tag, block_call),
2364+
Some(tag) => ExceptionTableItem::Tag(tag, block_call),
23752365
None => ExceptionTableItem::Default(block_call),
23762366
});
23772367
}
@@ -2457,7 +2447,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
24572447
}
24582448

24592449
fn attach_tags(&mut self, inst: ir::Inst) {
2460-
let tags = self.env.debug_tags(self.stack, self.srcloc);
2450+
let tags = self.env.debug_tags(self.srcloc);
24612451
if !tags.is_empty() {
24622452
self.builder.func.debug_tags.set(inst, tags);
24632453
}
@@ -2827,18 +2817,16 @@ impl FuncEnvironment<'_> {
28272817
builder: &mut FunctionBuilder<'_>,
28282818
tag_index: TagIndex,
28292819
args: &[ir::Value],
2830-
handlers: impl IntoIterator<Item = (Option<ExceptionTag>, Block)>,
28312820
) -> WasmResult<()> {
2832-
gc::translate_exn_throw(self, builder, tag_index, args, handlers)
2821+
gc::translate_exn_throw(self, builder, tag_index, args)
28332822
}
28342823

28352824
pub fn translate_exn_throw_ref(
28362825
&mut self,
28372826
builder: &mut FunctionBuilder<'_>,
28382827
exnref: ir::Value,
2839-
handlers: impl IntoIterator<Item = (Option<ExceptionTag>, Block)>,
28402828
) -> WasmResult<()> {
2841-
gc::translate_exn_throw_ref(self, builder, exnref, handlers)
2829+
gc::translate_exn_throw_ref(self, builder, exnref)
28422830
}
28432831

28442832
pub fn translate_array_new(
@@ -3206,17 +3194,15 @@ impl FuncEnvironment<'_> {
32063194
pub fn translate_call_indirect<'a>(
32073195
&mut self,
32083196
builder: &'a mut FunctionBuilder,
3209-
stack: &'a FuncTranslationStacks,
32103197
srcloc: ir::SourceLoc,
32113198
features: &WasmFeatures,
32123199
table_index: TableIndex,
32133200
ty_index: TypeIndex,
32143201
sig_ref: ir::SigRef,
32153202
callee: ir::Value,
32163203
call_args: &[ir::Value],
3217-
handlers: impl IntoIterator<Item = (Option<ExceptionTag>, Block)>,
32183204
) -> WasmResult<Option<CallRets>> {
3219-
Call::new(builder, self, stack, srcloc, handlers).indirect_call(
3205+
Call::new(builder, self, srcloc).indirect_call(
32203206
features,
32213207
table_index,
32223208
ty_index,
@@ -3229,54 +3215,40 @@ impl FuncEnvironment<'_> {
32293215
pub fn translate_call<'a>(
32303216
&mut self,
32313217
builder: &'a mut FunctionBuilder,
3232-
stack: &'a FuncTranslationStacks,
32333218
srcloc: ir::SourceLoc,
32343219
callee_index: FuncIndex,
32353220
sig_ref: ir::SigRef,
32363221
call_args: &[ir::Value],
3237-
handlers: impl IntoIterator<Item = (Option<ExceptionTag>, Block)>,
32383222
) -> WasmResult<CallRets> {
3239-
Call::new(builder, self, stack, srcloc, handlers).direct_call(
3240-
callee_index,
3241-
sig_ref,
3242-
call_args,
3243-
)
3223+
Call::new(builder, self, srcloc).direct_call(callee_index, sig_ref, call_args)
32443224
}
32453225

32463226
pub fn translate_call_ref<'a>(
32473227
&mut self,
32483228
builder: &'a mut FunctionBuilder,
3249-
stack: &'a FuncTranslationStacks,
32503229
srcloc: ir::SourceLoc,
32513230
sig_ref: ir::SigRef,
32523231
callee: ir::Value,
32533232
call_args: &[ir::Value],
3254-
handlers: impl IntoIterator<Item = (Option<ExceptionTag>, Block)>,
32553233
) -> WasmResult<CallRets> {
3256-
Call::new(builder, self, stack, srcloc, handlers).call_ref(sig_ref, callee, call_args)
3234+
Call::new(builder, self, srcloc).call_ref(sig_ref, callee, call_args)
32573235
}
32583236

32593237
pub fn translate_return_call(
32603238
&mut self,
32613239
builder: &mut FunctionBuilder,
3262-
stack: &FuncTranslationStacks,
32633240
srcloc: ir::SourceLoc,
32643241
callee_index: FuncIndex,
32653242
sig_ref: ir::SigRef,
32663243
call_args: &[ir::Value],
32673244
) -> WasmResult<()> {
3268-
Call::new_tail(builder, self, stack, srcloc).direct_call(
3269-
callee_index,
3270-
sig_ref,
3271-
call_args,
3272-
)?;
3245+
Call::new_tail(builder, self, srcloc).direct_call(callee_index, sig_ref, call_args)?;
32733246
Ok(())
32743247
}
32753248

32763249
pub fn translate_return_call_indirect(
32773250
&mut self,
32783251
builder: &mut FunctionBuilder,
3279-
stack: &FuncTranslationStacks,
32803252
srcloc: ir::SourceLoc,
32813253
features: &WasmFeatures,
32823254
table_index: TableIndex,
@@ -3285,7 +3257,7 @@ impl FuncEnvironment<'_> {
32853257
callee: ir::Value,
32863258
call_args: &[ir::Value],
32873259
) -> WasmResult<()> {
3288-
Call::new_tail(builder, self, stack, srcloc).indirect_call(
3260+
Call::new_tail(builder, self, srcloc).indirect_call(
32893261
features,
32903262
table_index,
32913263
ty_index,
@@ -3299,13 +3271,12 @@ impl FuncEnvironment<'_> {
32993271
pub fn translate_return_call_ref(
33003272
&mut self,
33013273
builder: &mut FunctionBuilder,
3302-
stack: &FuncTranslationStacks,
33033274
srcloc: ir::SourceLoc,
33043275
sig_ref: ir::SigRef,
33053276
callee: ir::Value,
33063277
call_args: &[ir::Value],
33073278
) -> WasmResult<()> {
3308-
Call::new_tail(builder, self, stack, srcloc).call_ref(sig_ref, callee, call_args)?;
3279+
Call::new_tail(builder, self, srcloc).call_ref(sig_ref, callee, call_args)?;
33093280
Ok(())
33103281
}
33113282

@@ -3765,14 +3736,13 @@ impl FuncEnvironment<'_> {
37653736
op: &Operator,
37663737
_operand_types: Option<&[WasmValType]>,
37673738
builder: &mut FunctionBuilder,
3768-
state: &FuncTranslationStacks,
37693739
) -> WasmResult<()> {
37703740
if self.tunables.consume_fuel {
3771-
self.fuel_before_op(op, builder, state.reachable());
3741+
self.fuel_before_op(op, builder, self.is_reachable());
37723742
}
3773-
if state.reachable() && self.state_slot.is_some() {
3743+
if self.is_reachable() && self.state_slot.is_some() {
37743744
let inst = builder.ins().sequence_point();
3775-
let tags = self.debug_tags(state, builder.srcloc());
3745+
let tags = self.debug_tags(builder.srcloc());
37763746
builder.func.debug_tags.set(inst, tags);
37773747
}
37783748

@@ -3784,13 +3754,12 @@ impl FuncEnvironment<'_> {
37843754
op: &Operator,
37853755
validator: &FuncValidator<impl WasmModuleResources>,
37863756
builder: &mut FunctionBuilder,
3787-
state: &mut FuncTranslationStacks,
37883757
) -> WasmResult<()> {
3789-
if self.tunables.consume_fuel && state.reachable() {
3758+
if self.tunables.consume_fuel && self.is_reachable() {
37903759
self.fuel_after_op(op, builder);
37913760
}
3792-
if state.reachable() {
3793-
self.update_state_slot_stack(validator, builder, state)?;
3761+
if self.is_reachable() {
3762+
self.update_state_slot_stack(validator, builder)?;
37943763
}
37953764
Ok(())
37963765
}
@@ -3802,11 +3771,7 @@ impl FuncEnvironment<'_> {
38023771
}
38033772
}
38043773

3805-
pub fn before_translate_function(
3806-
&mut self,
3807-
builder: &mut FunctionBuilder,
3808-
_state: &FuncTranslationStacks,
3809-
) -> WasmResult<()> {
3774+
pub fn before_translate_function(&mut self, builder: &mut FunctionBuilder) -> WasmResult<()> {
38103775
// If an explicit stack limit is requested, emit one here at the start
38113776
// of the function.
38123777
if let Some(gv) = self.stack_limit_at_function_entry {
@@ -3841,12 +3806,8 @@ impl FuncEnvironment<'_> {
38413806
Ok(())
38423807
}
38433808

3844-
pub fn after_translate_function(
3845-
&mut self,
3846-
builder: &mut FunctionBuilder,
3847-
state: &FuncTranslationStacks,
3848-
) -> WasmResult<()> {
3849-
if self.tunables.consume_fuel && state.reachable() {
3809+
pub fn after_translate_function(&mut self, builder: &mut FunctionBuilder) -> WasmResult<()> {
3810+
if self.tunables.consume_fuel && self.is_reachable() {
38503811
self.fuel_function_exit(builder);
38513812
}
38523813
self.finish_debug_metadata(builder);
@@ -4547,6 +4508,11 @@ impl FuncEnvironment<'_> {
45474508
pub fn is_pulley(&self) -> bool {
45484509
self.isa.triple().is_pulley()
45494510
}
4511+
4512+
/// Returns whether the current location is reachable.
4513+
pub fn is_reachable(&self) -> bool {
4514+
self.stacks.reachable()
4515+
}
45504516
}
45514517

45524518
// Helper function to convert an `IndexType` to an `ir::Type`.

crates/cranelift/src/func_environ/gc/disabled.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ pub fn translate_exn_throw(
7272
_builder: &mut FunctionBuilder<'_>,
7373
_tag_index: TagIndex,
7474
_args: &[ir::Value],
75-
_handlers: impl IntoIterator<Item = (Option<ir::ExceptionTag>, ir::Block)>,
7675
) -> WasmResult<()> {
7776
disabled()
7877
}
@@ -81,7 +80,6 @@ pub fn translate_exn_throw_ref(
8180
_func_env: &mut FuncEnvironment<'_>,
8281
_builder: &mut FunctionBuilder<'_>,
8382
_exnref: ir::Value,
84-
_handlers: impl IntoIterator<Item = (Option<ir::ExceptionTag>, ir::Block)>,
8583
) -> WasmResult<()> {
8684
disabled()
8785
}

0 commit comments

Comments
 (0)