Skip to content

Commit

Permalink
wasmtime: VMRuntimeLimits pointer is already SSA (#8689)
Browse files Browse the repository at this point in the history
* wasmtime: `VMRuntimeLimits` pointer is already SSA

We don't need to use cranelift-frontend to keep track of the location of
the `VMRuntimeLimits` pointer, because it is loaded once on entry to the
function and never changed afterward.

Instead, just track the correct SSA `Value`.

* Review comments: debug-assert it's initialized exactly once
  • Loading branch information
jameysharp authored May 24, 2024
1 parent ffd6bb5 commit f40aaa5
Showing 1 changed file with 17 additions and 20 deletions.
37 changes: 17 additions & 20 deletions crates/cranelift/src/func_environ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use cranelift_codegen::ir::pcc::Fact;
use cranelift_codegen::ir::types::*;
use cranelift_codegen::ir::{ArgumentPurpose, Function, InstBuilder, MemFlags};
use cranelift_codegen::isa::{TargetFrontendConfig, TargetIsa};
use cranelift_entity::packed_option::ReservedValue;
use cranelift_entity::{EntityRef, PrimaryMap, SecondaryMap};
use cranelift_frontend::FunctionBuilder;
use cranelift_frontend::Variable;
Expand Down Expand Up @@ -118,7 +119,7 @@ pub struct FuncEnvironment<'module_environment> {
/// VMRuntimeLimits` for this function's vmctx argument. This pointer is stored
/// in the vmctx itself, but never changes for the lifetime of the function,
/// so if we load it up front we can continue to use it throughout.
vmruntime_limits_ptr: cranelift_frontend::Variable,
vmruntime_limits_ptr: ir::Value,

/// A cached epoch deadline value, when performing epoch-based
/// interruption. Loaded from `VMRuntimeLimits` and reloaded after
Expand Down Expand Up @@ -171,7 +172,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
fuel_var: Variable::new(0),
epoch_deadline_var: Variable::new(0),
epoch_ptr_var: Variable::new(0),
vmruntime_limits_ptr: Variable::new(0),
vmruntime_limits_ptr: ir::Value::reserved_value(),

// Start with at least one fuel being consumed because even empty
// functions should consume at least some fuel.
Expand Down Expand Up @@ -284,14 +285,14 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
// function. This is possible since we know that the pointer never
// changes for the lifetime of the function.
let pointer_type = self.pointer_type();
builder.declare_var(self.vmruntime_limits_ptr, pointer_type);
let vmctx = self.vmctx(builder.func);
let base = builder.ins().global_value(pointer_type, vmctx);
let offset = i32::try_from(self.offsets.vmctx_runtime_limits()).unwrap();
let interrupt_ptr = builder
.ins()
.load(pointer_type, ir::MemFlags::trusted(), base, offset);
builder.def_var(self.vmruntime_limits_ptr, interrupt_ptr);
debug_assert!(self.vmruntime_limits_ptr.is_reserved_value());
self.vmruntime_limits_ptr =
builder
.ins()
.load(pointer_type, ir::MemFlags::trusted(), base, offset);
}

fn fuel_function_entry(&mut self, builder: &mut FunctionBuilder<'_>) {
Expand Down Expand Up @@ -438,7 +439,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {

/// Loads the fuel consumption value from `VMRuntimeLimits` into `self.fuel_var`
fn fuel_load_into_var(&mut self, builder: &mut FunctionBuilder<'_>) {
let (addr, offset) = self.fuel_addr_offset(builder);
let (addr, offset) = self.fuel_addr_offset();
let fuel = builder
.ins()
.load(ir::types::I64, ir::MemFlags::trusted(), addr, offset);
Expand All @@ -448,7 +449,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
/// Stores the fuel consumption value from `self.fuel_var` into
/// `VMRuntimeLimits`.
fn fuel_save_from_var(&mut self, builder: &mut FunctionBuilder<'_>) {
let (addr, offset) = self.fuel_addr_offset(builder);
let (addr, offset) = self.fuel_addr_offset();
let fuel_consumed = builder.use_var(self.fuel_var);
builder
.ins()
Expand All @@ -457,12 +458,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {

/// Returns the `(address, offset)` of the fuel consumption within
/// `VMRuntimeLimits`, used to perform loads/stores later.
fn fuel_addr_offset(
&mut self,
builder: &mut FunctionBuilder<'_>,
) -> (ir::Value, ir::immediates::Offset32) {
fn fuel_addr_offset(&mut self) -> (ir::Value, ir::immediates::Offset32) {
debug_assert!(!self.vmruntime_limits_ptr.is_reserved_value());
(
builder.use_var(self.vmruntime_limits_ptr),
self.vmruntime_limits_ptr,
i32::from(self.offsets.ptr.vmruntime_limits_fuel_consumed()).into(),
)
}
Expand Down Expand Up @@ -599,12 +598,11 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
}

fn epoch_load_deadline_into_var(&mut self, builder: &mut FunctionBuilder<'_>) {
let interrupts = builder.use_var(self.vmruntime_limits_ptr);
let deadline =
builder.ins().load(
ir::types::I64,
ir::MemFlags::trusted(),
interrupts,
self.vmruntime_limits_ptr,
ir::immediates::Offset32::new(
self.offsets.ptr.vmruntime_limits_epoch_deadline() as i32
),
Expand Down Expand Up @@ -1688,10 +1686,9 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
}

fn after_locals(&mut self, num_locals: usize) {
self.vmruntime_limits_ptr = Variable::new(num_locals);
self.fuel_var = Variable::new(num_locals + 1);
self.epoch_deadline_var = Variable::new(num_locals + 2);
self.epoch_ptr_var = Variable::new(num_locals + 3);
self.fuel_var = Variable::new(num_locals);
self.epoch_deadline_var = Variable::new(num_locals + 1);
self.epoch_ptr_var = Variable::new(num_locals + 2);
}

fn translate_table_grow(
Expand Down

0 comments on commit f40aaa5

Please sign in to comment.