Skip to content

Commit 6687e52

Browse files
authored
Refactor ModuleRegistry to not rely on image layout (#13483)
Prior to this commit the methods of `ModuleRegistry` implicitly relied on the in-memory layout of compiled modules/components, specifically that defined functions for modules were the only interesting functions and they're all clumped in groups. This reliance is surfaced in the `module_and_code_by_pc` method which was called for various operations such as when throwing an exception or looking at the stack for GC roots. In these scenarios, however, there's no need for a `Module` to be used and instead a bland `CodeMemory` can be used instead. This commit refactors the internals to no longer look at the `finished_functions` of a module and also avoid a `BTreeMap` within the `ModuleRegistry`. By doing so all methods are now fully agnostic to the internal layout of the code image of a module or component, which in turn empowers refactoring/moving various items around as needed. This is needed for an upcoming change I'm making, for example. Internally most users have moved over to `store_code_by_pc` since the call sites didn't need a module but instead "just some metadata". The main holdout is the logic to generate a trap frame from a stack walk. This is enabled by refactoring the previous `BTreeMap` to instead hold a `CompiledFunctionsTable`, used to translate a pc to a `FuncKey`, and then a mapping of `StaticModuleIndex` to `RegisteredModuleId`. This adds up to the ability to be able to go from an arbitrary pc to a module for a defined wasm function.
1 parent d70c1be commit 6687e52

9 files changed

Lines changed: 150 additions & 132 deletions

File tree

crates/wasmtime/src/runtime/code.rs

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,6 @@ impl EngineCode {
215215
self.original_code.exception_tables()
216216
}
217217

218-
/// Returns the encoded frame-tables section to pass to
219-
/// `wasmtime_environ::FrameTable::parse`.
220-
pub fn frame_tables(&self) -> &[u8] {
221-
self.original_code.frame_tables()
222-
}
223-
224218
/// Returns the data in the `ELF_NAME_DATA` section.
225219
#[inline]
226220
pub fn func_name_data(&self) -> &[u8] {
@@ -262,6 +256,12 @@ impl EngineCode {
262256
pub(crate) fn module_memory_image_source(&self) -> &Arc<impl ModuleMemoryImageSource> {
263257
&self.original_code
264258
}
259+
260+
/// See [`CodeMemory::frame_table`].
261+
#[cfg(feature = "debug")]
262+
pub(crate) fn frame_table<'a>(&'a self) -> Option<wasmtime_environ::FrameTable<'a>> {
263+
self.original_code.frame_table()
264+
}
265265
}
266266

267267
impl Drop for EngineCode {
@@ -430,23 +430,6 @@ impl<'a> ModuleWithCode<'a> {
430430
self.module
431431
}
432432

433-
/// Provide the StoreCode wrapped in this tuple.
434-
pub fn store_code(&self) -> &'a StoreCode {
435-
self.store_code
436-
}
437-
438-
/// Returns an iterator over all functions defined within this module with
439-
/// their index and their raw pointer.
440-
#[inline]
441-
pub fn finished_functions(
442-
&self,
443-
) -> impl ExactSizeIterator<Item = (DefinedFuncIndex, &[u8])> + '_ {
444-
self.module
445-
.env_module()
446-
.defined_func_indices()
447-
.map(|i| (i, self.finished_function(i)))
448-
}
449-
450433
/// Returns the slice in the text section of the function that
451434
/// `index` points to.
452435
#[inline]
@@ -474,20 +457,4 @@ impl<'a> ModuleWithCode<'a> {
474457
.array_to_wasm_trampoline_range(def_func_index)?;
475458
Some(&self.store_code.text()[range])
476459
}
477-
478-
/// Get the text offset (relative PC) for a given absolute PC in
479-
/// this module.
480-
#[cfg(feature = "gc")]
481-
pub(crate) fn text_offset(&self, pc: usize) -> Option<u32> {
482-
StoreCodePC::offset_of(self.store_code.text_range(), pc)
483-
.map(|offset| u32::try_from(offset).expect("Module larger than 4GiB"))
484-
}
485-
486-
/// Lookup the stack map at a program counter value.
487-
#[cfg(feature = "gc")]
488-
pub(crate) fn lookup_stack_map(&self, pc: usize) -> Option<wasmtime_environ::StackMap<'_>> {
489-
let text_offset = self.text_offset(pc)?;
490-
let info = self.module.engine_code().stack_map_data();
491-
wasmtime_environ::StackMap::lookup(text_offset, info)
492-
}
493460
}

crates/wasmtime/src/runtime/code_memory.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,22 @@ impl CodeMemory {
633633
let mmap = self.mmap.deep_clone()?;
634634
Self::new(engine, mmap)
635635
}
636+
637+
/// Obtain a frame-table parser on this module's frame state slot
638+
/// (debug instrumentation) metadata.
639+
#[cfg(feature = "debug")]
640+
pub(crate) fn frame_table(&self) -> Option<wasmtime_environ::FrameTable<'_>> {
641+
let data = self.frame_tables();
642+
if data.is_empty() {
643+
None
644+
} else {
645+
let orig_text = self.text();
646+
Some(
647+
wasmtime_environ::FrameTable::parse(data, orig_text)
648+
.expect("Frame tables were validated on module load"),
649+
)
650+
}
651+
}
636652
}
637653

638654
fn section_name<'a>(

crates/wasmtime/src/runtime/component/component.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,10 @@ impl Component {
933933
_ => unreachable!(),
934934
}
935935
}
936+
937+
pub(crate) fn index(&self) -> &Arc<CompiledFunctionsTable> {
938+
&self.inner.index
939+
}
936940
}
937941

938942
/// A value which represents a known export of a component.

crates/wasmtime/src/runtime/debug.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -645,10 +645,10 @@ impl FrameDataCache {
645645
// module that actually contains the physical PC
646646
// (i.e., the outermost function that inlined the
647647
// others).
648-
let (module, frames) = VirtualFrame::decode(registry, frame.pc());
648+
let (store_code, frames) = VirtualFrame::decode(registry, frame.pc());
649649
let frames = frames
650650
.into_iter()
651-
.map(|frame| FrameData::compute(frame, &module))
651+
.map(|frame| FrameData::compute(frame, store_code))
652652
.collect::<Vec<_>>();
653653
v.insert(frames)
654654
}
@@ -672,18 +672,17 @@ struct VirtualFrame {
672672
impl VirtualFrame {
673673
/// Return virtual frames corresponding to a physical frame, from
674674
/// outermost to innermost.
675-
fn decode(registry: &ModuleRegistry, pc: usize) -> (Module, Vec<VirtualFrame>) {
676-
let (module_with_code, pc) = registry
677-
.module_and_code_by_pc(pc)
675+
fn decode(registry: &ModuleRegistry, pc: usize) -> (&StoreCode, Vec<VirtualFrame>) {
676+
let (store_code, pc) = registry
677+
.store_code_by_pc(pc)
678678
.expect("Wasm frame PC does not correspond to a module");
679-
let module = module_with_code.module();
680-
let table = module.frame_table().unwrap();
679+
let table = store_code.code_memory().frame_table().unwrap();
681680
let pc = u32::try_from(pc).expect("PC offset too large");
682681
let program_points = table.find_program_point(pc, FrameInstPos::Post)
683682
.expect("There must be a program point record in every frame when debug instrumentation is enabled");
684683

685684
(
686-
module.clone(),
685+
store_code,
687686
program_points
688687
.map(|(wasm_pc, frame_descriptor, stack_shape)| VirtualFrame {
689688
wasm_pc,
@@ -719,8 +718,8 @@ struct FrameData {
719718
}
720719

721720
impl FrameData {
722-
fn compute(frame: VirtualFrame, module: &Module) -> Self {
723-
let frame_table = module.frame_table().unwrap();
721+
fn compute(frame: VirtualFrame, store_code: &StoreCode) -> Self {
722+
let frame_table = store_code.code_memory().frame_table().unwrap();
724723
// Parse the frame descriptor.
725724
let (data, slot_to_fp_offset) = frame_table
726725
.frame_descriptor(frame.frame_descriptor)

crates/wasmtime/src/runtime/instantiate.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ impl CompiledModule {
267267
self.engine_code
268268
.wasm_bytecode_for_module(self.module.module_index)
269269
}
270+
271+
pub(crate) fn index(&self) -> &Arc<CompiledFunctionsTable> {
272+
&self.index
273+
}
270274
}
271275

272276
#[cfg(feature = "addr2line")]

crates/wasmtime/src/runtime/module.rs

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,10 @@ use core::ptr::NonNull;
1818
#[cfg(feature = "std")]
1919
use std::{fs::File, path::Path};
2020
use wasmparser::{Parser, ValidPayload, Validator};
21-
#[cfg(feature = "debug")]
22-
use wasmtime_environ::FrameTable;
2321
use wasmtime_environ::{
2422
CompiledFunctionsTable, CompiledModuleInfo, EntityIndex, HostPtr, ModuleTypes, ObjectKind,
2523
StaticModuleIndex, TypeTrace, VMOffsets, VMSharedTypeIndex, WasmChecksum,
2624
};
27-
#[cfg(feature = "gc")]
28-
use wasmtime_unwinder::ExceptionTable;
2925
mod registry;
3026

3127
pub use registry::*;
@@ -1178,27 +1174,10 @@ impl Module {
11781174
Ok(images)
11791175
}
11801176

1181-
/// Obtain an exception-table parser on this module's exception metadata.
1182-
#[cfg(feature = "gc")]
1183-
pub(crate) fn exception_table<'a>(&'a self) -> ExceptionTable<'a> {
1184-
ExceptionTable::parse(self.inner.code.exception_tables())
1185-
.expect("Exception tables were validated on module load")
1186-
}
1187-
1188-
/// Obtain a frame-table parser on this module's frame state slot
1189-
/// (debug instrumentation) metadata.
1177+
/// See [`CodeMemory::frame_table`].
11901178
#[cfg(feature = "debug")]
1191-
pub(crate) fn frame_table<'a>(&'a self) -> Option<FrameTable<'a>> {
1192-
let data = self.inner.code.frame_tables();
1193-
if data.is_empty() {
1194-
None
1195-
} else {
1196-
let orig_text = self.inner.code.text();
1197-
Some(
1198-
FrameTable::parse(data, orig_text)
1199-
.expect("Frame tables were validated on module load"),
1200-
)
1201-
}
1179+
pub(crate) fn frame_table<'a>(&'a self) -> Option<wasmtime_environ::FrameTable<'a>> {
1180+
self.inner.code.frame_table()
12021181
}
12031182

12041183
/// Is this `Module` the same as another?
@@ -1216,6 +1195,10 @@ impl Module {
12161195
pub fn same(a: &Module, b: &Module) -> bool {
12171196
Arc::ptr_eq(&a.inner, &b.inner)
12181197
}
1198+
1199+
pub(crate) fn index(&self) -> &Arc<CompiledFunctionsTable> {
1200+
&self.inner.module.index()
1201+
}
12191202
}
12201203

12211204
/// Describes a function for a given module.

0 commit comments

Comments
 (0)