Skip to content

Commit 980f302

Browse files
committed
Analyze whether a module requires a GC heap during its compilation
And avoid forcing the allocation of a GC heap for modules that will not use it. Split out from bytecodealliance#9350
1 parent b152712 commit 980f302

File tree

19 files changed

+247
-112
lines changed

19 files changed

+247
-112
lines changed

crates/cranelift/src/compiler.rs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ use std::path;
2727
use std::sync::{Arc, Mutex};
2828
use wasmparser::{FuncValidatorAllocations, FunctionBody};
2929
use wasmtime_environ::{
30-
AddressMapSection, BuiltinFunctionIndex, CacheStore, CompileError, DefinedFuncIndex, FlagValue,
31-
FunctionBodyData, FunctionLoc, HostCall, ModuleTranslation, ModuleTypesBuilder, PtrSize,
32-
RelocationTarget, StackMapSection, StaticModuleIndex, TrapEncodingBuilder, TrapSentinel,
33-
TripleExt, Tunables, VMOffsets, WasmFuncType, WasmValType,
30+
AddressMapSection, BuiltinFunctionIndex, CacheStore, CompileError, CompiledFunctionBody,
31+
DefinedFuncIndex, FlagValue, FunctionBodyData, FunctionLoc, HostCall, ModuleTranslation,
32+
ModuleTypesBuilder, PtrSize, RelocationTarget, StackMapSection, StaticModuleIndex,
33+
TrapEncodingBuilder, TrapSentinel, TripleExt, Tunables, VMOffsets, WasmFuncType, WasmValType,
3434
};
3535

3636
#[cfg(feature = "component-model")]
@@ -187,7 +187,7 @@ impl wasmtime_environ::Compiler for Compiler {
187187
func_index: DefinedFuncIndex,
188188
input: FunctionBodyData<'_>,
189189
types: &ModuleTypesBuilder,
190-
) -> Result<Box<dyn Any + Send>, CompileError> {
190+
) -> Result<CompiledFunctionBody, CompileError> {
191191
let isa = &*self.isa;
192192
let module = &translation.module;
193193
let func_index = module.func_index(func_index);
@@ -284,15 +284,18 @@ impl wasmtime_environ::Compiler for Compiler {
284284
log::debug!("{:?} translated in {:?}", func_index, timing.total());
285285
log::trace!("{:?} timing info\n{}", func_index, timing);
286286

287-
Ok(Box::new(func))
287+
Ok(CompiledFunctionBody {
288+
code: Box::new(func),
289+
needs_gc_heap: func_env.needs_gc_heap(),
290+
})
288291
}
289292

290293
fn compile_array_to_wasm_trampoline(
291294
&self,
292295
translation: &ModuleTranslation<'_>,
293296
types: &ModuleTypesBuilder,
294297
def_func_index: DefinedFuncIndex,
295-
) -> Result<Box<dyn Any + Send>, CompileError> {
298+
) -> Result<CompiledFunctionBody, CompileError> {
296299
let func_index = translation.module.func_index(def_func_index);
297300
let sig = translation.module.functions[func_index]
298301
.signature
@@ -359,16 +362,16 @@ impl wasmtime_environ::Compiler for Compiler {
359362
builder.ins().return_(&[true_return]);
360363
builder.finalize();
361364

362-
Ok(Box::new(compiler.finish(&format!(
363-
"array_to_wasm_{}",
364-
func_index.as_u32(),
365-
))?))
365+
Ok(CompiledFunctionBody {
366+
code: Box::new(compiler.finish(&format!("array_to_wasm_{}", func_index.as_u32(),))?),
367+
needs_gc_heap: false,
368+
})
366369
}
367370

368371
fn compile_wasm_to_array_trampoline(
369372
&self,
370373
wasm_func_ty: &WasmFuncType,
371-
) -> Result<Box<dyn Any + Send>, CompileError> {
374+
) -> Result<CompiledFunctionBody, CompileError> {
372375
let isa = &*self.isa;
373376
let pointer_type = isa.pointer_type();
374377
let wasm_call_sig = wasm_call_signature(isa, wasm_func_ty, &self.tunables);
@@ -432,9 +435,10 @@ impl wasmtime_environ::Compiler for Compiler {
432435
builder.ins().return_(&results);
433436
builder.finalize();
434437

435-
Ok(Box::new(compiler.finish(&format!(
436-
"wasm_to_array_trampoline_{wasm_func_ty}"
437-
))?))
438+
Ok(CompiledFunctionBody {
439+
code: Box::new(compiler.finish(&format!("wasm_to_array_trampoline_{wasm_func_ty}"))?),
440+
needs_gc_heap: false,
441+
})
438442
}
439443

440444
fn append_code(
@@ -582,7 +586,7 @@ impl wasmtime_environ::Compiler for Compiler {
582586
fn compile_wasm_to_builtin(
583587
&self,
584588
index: BuiltinFunctionIndex,
585-
) -> Result<Box<dyn Any + Send>, CompileError> {
589+
) -> Result<CompiledFunctionBody, CompileError> {
586590
let isa = &*self.isa;
587591
let ptr_size = isa.pointer_bytes();
588592
let pointer_type = isa.pointer_type();
@@ -651,9 +655,10 @@ impl wasmtime_environ::Compiler for Compiler {
651655
builder.ins().return_(&results);
652656
builder.finalize();
653657

654-
Ok(Box::new(
655-
compiler.finish(&format!("wasm_to_builtin_{}", index.name()))?,
656-
))
658+
Ok(CompiledFunctionBody {
659+
code: Box::new(compiler.finish(&format!("wasm_to_builtin_{}", index.name()))?),
660+
needs_gc_heap: false,
661+
})
657662
}
658663

659664
fn compiled_function_relocation_targets<'a>(

crates/cranelift/src/compiler/component.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ use cranelift_codegen::ir::condcodes::IntCC;
66
use cranelift_codegen::ir::{self, InstBuilder, MemFlags, Value};
77
use cranelift_codegen::isa::{CallConv, TargetIsa};
88
use cranelift_frontend::FunctionBuilder;
9-
use std::any::Any;
10-
use wasmtime_environ::component::*;
119
use wasmtime_environ::fact::SYNC_ENTER_FIXED_PARAMS;
10+
use wasmtime_environ::{component::*, CompiledFunctionBody};
1211
use wasmtime_environ::{
1312
HostCall, ModuleInternedTypeIndex, PtrSize, TrapSentinel, Tunables, WasmFuncType, WasmValType,
1413
};
@@ -1450,7 +1449,7 @@ impl ComponentCompiler for Compiler {
14501449
types: &ComponentTypesBuilder,
14511450
index: TrampolineIndex,
14521451
tunables: &Tunables,
1453-
) -> Result<AllCallFunc<Box<dyn Any + Send>>> {
1452+
) -> Result<AllCallFunc<CompiledFunctionBody>> {
14541453
let compile = |abi: Abi| -> Result<_> {
14551454
let mut compiler = self.function_compiler();
14561455
let mut c = TrampolineCompiler::new(
@@ -1494,10 +1493,12 @@ impl ComponentCompiler for Compiler {
14941493
c.translate(&component.trampolines[index]);
14951494
c.builder.finalize();
14961495

1497-
Ok(Box::new(compiler.finish(&format!(
1498-
"component_trampoline_{}_{abi:?}",
1499-
index.as_u32(),
1500-
))?))
1496+
Ok(CompiledFunctionBody {
1497+
code: Box::new(
1498+
compiler.finish(&format!("component_trampoline_{}_{abi:?}", index.as_u32()))?,
1499+
),
1500+
needs_gc_heap: false,
1501+
})
15011502
};
15021503
Ok(AllCallFunc {
15031504
wasm_call: compile(Abi::Wasm)?,

crates/cranelift/src/func_environ.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use cranelift_codegen::ir::types::*;
1414
use cranelift_codegen::ir::{self, types};
1515
use cranelift_codegen::ir::{ArgumentPurpose, Function, InstBuilder, MemFlags};
1616
use cranelift_codegen::isa::{TargetFrontendConfig, TargetIsa};
17-
use cranelift_entity::packed_option::ReservedValue;
17+
use cranelift_entity::packed_option::ReservedValue as _;
1818
use cranelift_entity::{EntityRef, PrimaryMap, SecondaryMap};
1919
use cranelift_frontend::FunctionBuilder;
2020
use cranelift_frontend::Variable;
@@ -98,6 +98,7 @@ pub struct FuncEnvironment<'module_environment> {
9898
types: &'module_environment ModuleTypesBuilder,
9999
wasm_func_ty: &'module_environment WasmFuncType,
100100
sig_ref_to_ty: SecondaryMap<ir::SigRef, Option<&'module_environment WasmFuncType>>,
101+
needs_gc_heap: bool,
101102

102103
#[cfg(feature = "gc")]
103104
ty_to_gc_layout: std::collections::HashMap<
@@ -187,6 +188,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
187188
types,
188189
wasm_func_ty,
189190
sig_ref_to_ty: SecondaryMap::default(),
191+
needs_gc_heap: false,
190192

191193
#[cfg(feature = "gc")]
192194
ty_to_gc_layout: std::collections::HashMap::new(),
@@ -1194,6 +1196,11 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
11941196
i32::from(self.offsets.ptr.vm_func_ref_type_index()),
11951197
)
11961198
}
1199+
1200+
/// Does this function need a GC heap?
1201+
pub fn needs_gc_heap(&self) -> bool {
1202+
self.needs_gc_heap
1203+
}
11971204
}
11981205

11991206
struct Call<'a, 'func, 'module_env> {

crates/cranelift/src/func_environ/gc.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,19 @@ pub mod builtins {
163163
func: &mut ir::Function,
164164
) -> WasmResult<ir::FuncRef> {
165165
#[cfg(feature = "gc")]
166-
return Ok(func_env.builtin_functions.$name(func));
166+
{
167+
func_env.needs_gc_heap = true;
168+
return Ok(func_env.builtin_functions.$name(func));
169+
}
167170

168171
#[cfg(not(feature = "gc"))]
169-
let _ = (func, func_env);
170-
#[cfg(not(feature = "gc"))]
171-
return Err(wasmtime_environ::wasm_unsupported!(
172-
"support for Wasm GC disabled at compile time because the `gc` cargo \
173-
feature was not enabled"
174-
));
172+
{
173+
let _ = (func, func_env);
174+
return Err(wasmtime_environ::wasm_unsupported!(
175+
"support for Wasm GC disabled at compile time because the `gc` cargo \
176+
feature was not enabled"
177+
));
178+
}
175179
}
176180
)*
177181
};

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ mod drc;
2121
mod null;
2222

2323
/// Get the default GC compiler.
24-
pub fn gc_compiler(func_env: &FuncEnvironment<'_>) -> WasmResult<Box<dyn GcCompiler>> {
24+
pub fn gc_compiler(func_env: &mut FuncEnvironment<'_>) -> WasmResult<Box<dyn GcCompiler>> {
25+
// If this function requires a GC compiler, that is not too bad of an
26+
// over-approximation for it requiring a GC heap.
27+
func_env.needs_gc_heap = true;
28+
2529
match func_env.tunables.collector {
2630
#[cfg(feature = "gc-drc")]
2731
Some(Collector::DeferredReferenceCounting) => Ok(Box::new(drc::DrcCompiler::default())),

crates/environ/src/compile/mod.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,16 @@ pub enum SettingKind {
178178
Preset,
179179
}
180180

181+
/// The result of compiling a single function body.
182+
pub struct CompiledFunctionBody {
183+
/// The code. This is whatever type the `Compiler` implementation wants it
184+
/// to be, we just shepherd it around.
185+
pub code: Box<dyn Any + Send>,
186+
/// Whether the compiled function needs a GC heap to run; that is, whether
187+
/// it reads a struct field, allocates, an array, or etc...
188+
pub needs_gc_heap: bool,
189+
}
190+
181191
/// An implementation of a compiler which can compile WebAssembly functions to
182192
/// machine code and perform other miscellaneous tasks needed by the JIT runtime.
183193
pub trait Compiler: Send + Sync {
@@ -186,19 +196,13 @@ pub trait Compiler: Send + Sync {
186196
/// The body of the function is available in `data` and configuration
187197
/// values are also passed in via `tunables`. Type information in
188198
/// `translation` is all relative to `types`.
189-
///
190-
/// This function returns a tuple:
191-
///
192-
/// 1. Metadata about the wasm function itself.
193-
/// 2. The function itself, as an `Any` to get downcasted later when passed
194-
/// to `append_code`.
195199
fn compile_function(
196200
&self,
197201
translation: &ModuleTranslation<'_>,
198202
index: DefinedFuncIndex,
199203
data: FunctionBodyData<'_>,
200204
types: &ModuleTypesBuilder,
201-
) -> Result<Box<dyn Any + Send>, CompileError>;
205+
) -> Result<CompiledFunctionBody, CompileError>;
202206

203207
/// Compile a trampoline for an array-call host function caller calling the
204208
/// `index`th Wasm function.
@@ -210,7 +214,7 @@ pub trait Compiler: Send + Sync {
210214
translation: &ModuleTranslation<'_>,
211215
types: &ModuleTypesBuilder,
212216
index: DefinedFuncIndex,
213-
) -> Result<Box<dyn Any + Send>, CompileError>;
217+
) -> Result<CompiledFunctionBody, CompileError>;
214218

215219
/// Compile a trampoline for a Wasm caller calling a array callee with the
216220
/// given signature.
@@ -220,7 +224,7 @@ pub trait Compiler: Send + Sync {
220224
fn compile_wasm_to_array_trampoline(
221225
&self,
222226
wasm_func_ty: &WasmFuncType,
223-
) -> Result<Box<dyn Any + Send>, CompileError>;
227+
) -> Result<CompiledFunctionBody, CompileError>;
224228

225229
/// Creates a trampoline that can be used to call Wasmtime's implementation
226230
/// of the builtin function specified by `index`.
@@ -234,7 +238,7 @@ pub trait Compiler: Send + Sync {
234238
fn compile_wasm_to_builtin(
235239
&self,
236240
index: BuiltinFunctionIndex,
237-
) -> Result<Box<dyn Any + Send>, CompileError>;
241+
) -> Result<CompiledFunctionBody, CompileError>;
238242

239243
/// Returns the list of relocations required for a function from one of the
240244
/// previous `compile_*` functions above.

crates/environ/src/component/compiler.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use crate::component::{AllCallFunc, ComponentTranslation, ComponentTypesBuilder, TrampolineIndex};
2-
use crate::prelude::*;
3-
use crate::Tunables;
2+
use crate::{CompiledFunctionBody, Tunables};
43
use anyhow::Result;
5-
use std::any::Any;
64

75
/// Compilation support necessary for components.
86
pub trait ComponentCompiler: Send + Sync {
@@ -18,5 +16,5 @@ pub trait ComponentCompiler: Send + Sync {
1816
types: &ComponentTypesBuilder,
1917
trampoline: TrampolineIndex,
2018
tunables: &Tunables,
21-
) -> Result<AllCallFunc<Box<dyn Any + Send>>>;
19+
) -> Result<AllCallFunc<CompiledFunctionBody>>;
2220
}

crates/environ/src/module.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,9 @@ pub struct Module {
336336
/// Number of imported or aliased tags in the module.
337337
pub num_imported_tags: usize,
338338

339+
/// Does this module need a GC heap to run?
340+
pub needs_gc_heap: bool,
341+
339342
/// Number of functions that "escape" from this module may need to have a
340343
/// `VMFuncRef` constructed for them.
341344
///
@@ -616,6 +619,7 @@ impl TypeTrace for Module {
616619
num_imported_globals: _,
617620
num_imported_tags: _,
618621
num_escaped_funcs: _,
622+
needs_gc_heap: _,
619623
functions,
620624
tables,
621625
memories: _,
@@ -665,6 +669,7 @@ impl TypeTrace for Module {
665669
num_imported_globals: _,
666670
num_imported_tags: _,
667671
num_escaped_funcs: _,
672+
needs_gc_heap: _,
668673
functions,
669674
tables,
670675
memories: _,

0 commit comments

Comments
 (0)