Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 9707362

Browse files
committed
Let EnvState own its own compiler instead of unsafe lifetime cast.
1 parent 6ba14dd commit 9707362

File tree

3 files changed

+39
-34
lines changed

3 files changed

+39
-34
lines changed

core/executor/src/wasmtime/function_executor.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,14 @@ pub struct SupervisorFuncRef(*const VMCallerCheckedAnyfunc);
4848
///
4949
/// This is stored as part of the host state of the "env" Wasmtime instance.
5050
pub struct FunctionExecutorState {
51-
// The lifetime of the reference is not actually static, but is unsafely cast to static since
52-
// the compiler is owned by the wasmtime-jit `Context` and must be accessed during host calls.
53-
compiler: &'static mut Compiler,
5451
sandbox_store: sandbox::Store<SupervisorFuncRef>,
5552
heap: FreeingBumpHeapAllocator,
5653
}
5754

5855
impl FunctionExecutorState {
5956
/// Constructs a new `FunctionExecutorState`.
60-
pub fn new(compiler: &'static mut Compiler, heap_base: u32) -> Self {
57+
pub fn new(heap_base: u32) -> Self {
6158
FunctionExecutorState {
62-
compiler,
6359
sandbox_store: sandbox::Store::new(),
6460
heap: FreeingBumpHeapAllocator::new(heap_base),
6561
}
@@ -87,8 +83,11 @@ impl<'a> FunctionExecutor<'a> {
8783
///
8884
/// The vmctx MUST come from a call to a function in the "env" module.
8985
/// The state MUST be looked up from the host state of the "env" module.
90-
pub unsafe fn new(vmctx: *mut VMContext, state: &'a mut FunctionExecutorState)
91-
-> Result<Self>
86+
pub unsafe fn new(
87+
vmctx: *mut VMContext,
88+
compiler: &'a mut Compiler,
89+
state: &'a mut FunctionExecutorState,
90+
) -> Result<Self>
9291
{
9392
let memory = match (*vmctx).lookup_global_export("memory") {
9493
Some(Export::Memory { definition, vmctx: _, memory: _ }) =>
@@ -107,7 +106,7 @@ impl<'a> FunctionExecutor<'a> {
107106
_ => None,
108107
};
109108
Ok(FunctionExecutor {
110-
compiler: &mut state.compiler,
109+
compiler,
111110
sandbox_store: &mut state.sandbox_store,
112111
heap: &mut state.heap,
113112
memory,

core/executor/src/wasmtime/runtime.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use cranelift_wasm::DefinedFuncIndex;
3333
use std::cell::RefCell;
3434
use std::collections::HashMap;
3535
use std::convert::TryFrom;
36-
use std::mem;
3736
use std::rc::Rc;
3837
use wasm_interface::{HostFunctions, Pointer, WordSize};
3938
use wasmtime_environ::{Module, translate_signature};
@@ -128,15 +127,18 @@ pub fn create_instance<E: Externalities>(ext: &mut E, code: &[u8], heap_pages: u
128127
fn create_compiled_unit(code: &[u8])
129128
-> std::result::Result<(CompiledModule, Context), WasmError>
130129
{
131-
let isa = target_isa()?;
132-
let mut context = Context::with_isa(isa, CompilationStrategy::Cranelift);
130+
let compilation_strategy = CompilationStrategy::Cranelift;
131+
132+
let compiler = new_compiler(compilation_strategy)?;
133+
let mut context = Context::new(Box::new(compiler));
133134

134135
// Enable/disable producing of debug info.
135136
context.set_debug_info(false);
136137

137138
// Instantiate and link the env module.
138139
let global_exports = context.get_global_exports();
139-
let env_module = instantiate_env_module(global_exports)?;
140+
let compiler = new_compiler(compilation_strategy)?;
141+
let env_module = instantiate_env_module(global_exports, compiler)?;
140142
context.name_instance("env".to_owned(), env_module);
141143

142144
// Compile the wasm module.
@@ -173,15 +175,8 @@ fn call_method(
173175
grow_memory(&mut instance, heap_pages)?;
174176

175177
// Initialize the function executor state.
176-
let executor_state = FunctionExecutorState::new(
177-
// Unsafely extend the reference lifetime to static. This is necessary because the
178-
// host state must be `Any`. This is OK as we will drop this object either before
179-
// exiting the function in the happy case or in the worst case on the next runtime
180-
// call, which also resets the host state. Thus this reference can never actually
181-
// outlive the Context.
182-
unsafe { mem::transmute::<_, &'static mut Compiler>(context.compiler_mut()) },
183-
get_heap_base(&instance)?,
184-
);
178+
let heap_base = get_heap_base(&instance)?;
179+
let executor_state = FunctionExecutorState::new(heap_base);
185180
reset_env_state(context, Some(executor_state))?;
186181

187182
// Write the input data into guest memory.
@@ -222,8 +217,10 @@ fn call_method(
222217
}
223218

224219
/// The implementation is based on wasmtime_wasi::instantiate_wasi.
225-
fn instantiate_env_module(global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>)
226-
-> std::result::Result<InstanceHandle, WasmError>
220+
fn instantiate_env_module(
221+
global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>,
222+
compiler: Compiler,
223+
) -> std::result::Result<InstanceHandle, WasmError>
227224
{
228225
let isa = target_isa()?;
229226
let pointer_type = isa.pointer_type();
@@ -260,7 +257,7 @@ fn instantiate_env_module(global_exports: Rc<RefCell<HashMap<String, Option<Expo
260257
let imports = Imports::none();
261258
let data_initializers = Vec::new();
262259
let signatures = PrimaryMap::new();
263-
let env_state = EnvState::new::<SubstrateExternals>(code_memory);
260+
let env_state = EnvState::new::<SubstrateExternals>(code_memory, compiler);
264261

265262
let result = InstanceHandle::new(
266263
Rc::new(module),
@@ -283,6 +280,11 @@ fn target_isa() -> std::result::Result<Box<dyn TargetIsa>, WasmError> {
283280
Ok(isa_builder.finish(cranelift_codegen::settings::Flags::new(flag_builder)))
284281
}
285282

283+
fn new_compiler(strategy: CompilationStrategy) -> std::result::Result<Compiler, WasmError> {
284+
let isa = target_isa()?;
285+
Ok(Compiler::new(isa, strategy))
286+
}
287+
286288
fn clear_globals(global_exports: &mut HashMap<String, Option<Export>>) {
287289
global_exports.remove("memory");
288290
global_exports.remove("__heap_base");

core/executor/src/wasmtime/trampoline.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
use cranelift_codegen::{Context, binemit, ir, isa};
2323
use cranelift_codegen::ir::{InstBuilder, StackSlotData, StackSlotKind, TrapCode};
2424
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
25-
use wasmtime_jit::CodeMemory;
25+
use wasmtime_jit::{CodeMemory, Compiler};
2626
use wasmtime_runtime::{VMContext, VMFunctionBody};
2727
use wasm_interface::{HostFunctions, Function, Value, ValueType};
28-
use std::{cmp, mem, ptr};
28+
use std::{cmp, ptr};
2929

3030
use crate::error::{Error, Result};
3131
use crate::wasmtime::function_executor::{FunctionExecutorState, FunctionExecutor};
@@ -34,23 +34,25 @@ use crate::wasmtime::function_executor::{FunctionExecutorState, FunctionExecutor
3434
/// construct a `FunctionExecutor` which can execute the host call.
3535
pub struct EnvState {
3636
externals: &'static [&'static dyn Function],
37+
compiler: Compiler,
38+
// The code memory must be kept around on the state to prevent it from being dropped.
39+
#[allow(dead_code)]
40+
code_memory: CodeMemory,
3741
trap: Option<Error>,
3842
/// The executor state stored across host calls during a single Wasm runtime call.
3943
/// During a runtime call, this MUST be `Some`.
4044
pub executor_state: Option<FunctionExecutorState>,
41-
// The code memory must be kept around on the state to prevent it from being dropped.
42-
#[allow(dead_code)]
43-
code_memory: CodeMemory,
4445
}
4546

4647
impl EnvState {
4748
/// Construct a new `EnvState` which owns the given code memory.
48-
pub fn new<HF: HostFunctions>(code_memory: CodeMemory) -> Self {
49+
pub fn new<HF: HostFunctions>(code_memory: CodeMemory, compiler: Compiler) -> Self {
4950
EnvState {
5051
externals: HF::functions(),
5152
trap: None,
52-
executor_state: None,
53+
compiler,
5354
code_memory,
55+
executor_state: None,
5456
}
5557
}
5658

@@ -67,8 +69,9 @@ unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, func_index: u32, values_vec:
6769
match stub_fn_inner(
6870
vmctx,
6971
state.externals,
70-
func_index,
72+
&mut state.compiler,
7173
state.executor_state.as_mut(),
74+
func_index,
7275
values_vec
7376
) {
7477
Ok(()) => 0,
@@ -88,8 +91,9 @@ unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, func_index: u32, values_vec:
8891
unsafe fn stub_fn_inner(
8992
vmctx: *mut VMContext,
9093
externals: &[&dyn Function],
91-
func_index: u32,
94+
compiler: &mut Compiler,
9295
executor_state: Option<&mut FunctionExecutorState>,
96+
func_index: u32,
9397
values_vec: *mut i64,
9498
) -> Result<()>
9599
{
@@ -99,7 +103,7 @@ unsafe fn stub_fn_inner(
99103
.ok_or_else(|| "executor state is None during call to external function")?;
100104

101105
// Build the external function context.
102-
let mut context = FunctionExecutor::new(vmctx, executor_state)?;
106+
let mut context = FunctionExecutor::new(vmctx, compiler, executor_state)?;
103107

104108
let signature = func.signature();
105109

0 commit comments

Comments
 (0)