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

Commit 4e770b4

Browse files
committed
WIP state holder via *mut
1 parent 1be139b commit 4e770b4

File tree

3 files changed

+154
-68
lines changed

3 files changed

+154
-68
lines changed

client/executor/common/src/sandbox.rs

Lines changed: 90 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,9 @@ impl<FR> SandboxInstance<FR> {
362362
///
363363
/// The `state` parameter can be used to provide custom data for
364364
/// these syscall implementations.
365-
pub fn invoke<FE: SandboxCapabilities<SupervisorFuncRef=FR>>(
365+
pub fn invoke
366+
//<FE: SandboxCapabilities<SupervisorFuncRef=FR>>
367+
(
366368
&self,
367369

368370
// function to call that is exported from the module
@@ -372,55 +374,58 @@ impl<FR> SandboxInstance<FR> {
372374
args: &[RuntimeValue],
373375

374376
// supervisor environment provided to the module
375-
supervisor_externals: &mut FE,
377+
// supervisor_externals: &mut FE,
376378

377379
// arbitraty context data of the call
378380
state: u32,
379381
) -> std::result::Result<Option<wasmi::RuntimeValue>, wasmi::Error> {
380-
with_guest_externals(
381-
supervisor_externals,
382-
self,
383-
state,
384-
|guest_externals| {
385382

386-
let wasmi_result = self.wasmi_instance
387-
.invoke_export(export_name, args, guest_externals)?;
388-
389-
let wasmtime_function = self
390-
.wasmtime_instance
391-
.get_func(export_name)
392-
.ok_or(wasmi::Error::Function("wasmtime function failed".to_string()))?;
393-
394-
let args: Vec<Val> = args
395-
.iter()
396-
.map(|v| match *v {
397-
RuntimeValue::I32(val) => Val::I32(val),
398-
RuntimeValue::I64(val) => Val::I64(val),
399-
RuntimeValue::F32(val) => Val::F32(val.into()),
400-
RuntimeValue::F64(val) => Val::F64(val.into()),
401-
})
402-
.collect();
403-
404-
let wasmtime_result = wasmtime_function
405-
.call(&args)
406-
.map_err(|e| wasmi::Error::Function(e.to_string()))?;
407-
408-
assert_eq!(wasmtime_result.len(), 1, "multiple return types are not supported yet");
409-
if let Some(wasmi_value) = wasmi_result {
410-
let wasmtime_value = match *wasmtime_result.first().unwrap() {
411-
Val::I32(val) => RuntimeValue::I32(val),
412-
Val::I64(val) => RuntimeValue::I64(val),
413-
Val::F32(val) => RuntimeValue::F32(val.into()),
414-
Val::F64(val) => RuntimeValue::F64(val.into()),
415-
_ => unreachable!(),
416-
};
417-
418-
assert_eq!(wasmi_value, wasmtime_value, "return values do not match");
419-
}
420-
421-
Ok(wasmi_result)
422-
},
423-
)
383+
SCH::with_sandbox_capabilities( |supervisor_externals| {
384+
with_guest_externals(
385+
supervisor_externals,
386+
self,
387+
state,
388+
|guest_externals| {
389+
390+
let wasmi_result = self.wasmi_instance
391+
.invoke_export(export_name, args, guest_externals)?;
392+
393+
let wasmtime_function = self
394+
.wasmtime_instance
395+
.get_func(export_name)
396+
.ok_or(wasmi::Error::Function("wasmtime function failed".to_string()))?;
397+
398+
let args: Vec<Val> = args
399+
.iter()
400+
.map(|v| match *v {
401+
RuntimeValue::I32(val) => Val::I32(val),
402+
RuntimeValue::I64(val) => Val::I64(val),
403+
RuntimeValue::F32(val) => Val::F32(val.into()),
404+
RuntimeValue::F64(val) => Val::F64(val.into()),
405+
})
406+
.collect();
407+
408+
let wasmtime_result = wasmtime_function
409+
.call(&args)
410+
.map_err(|e| wasmi::Error::Function(e.to_string()))?;
411+
412+
assert_eq!(wasmtime_result.len(), 1, "multiple return types are not supported yet");
413+
if let Some(wasmi_value) = wasmi_result {
414+
let wasmtime_value = match *wasmtime_result.first().unwrap() {
415+
Val::I32(val) => RuntimeValue::I32(val),
416+
Val::I64(val) => RuntimeValue::I64(val),
417+
Val::F32(val) => RuntimeValue::F32(val.into()),
418+
Val::F64(val) => RuntimeValue::F64(val.into()),
419+
_ => unreachable!(),
420+
};
421+
422+
assert_eq!(wasmi_value, wasmtime_value, "return values do not match");
423+
}
424+
425+
Ok(wasmi_result)
426+
},
427+
)
428+
})
424429
}
425430

426431
/// Get the value from a global with the given `name`.
@@ -547,6 +552,13 @@ impl<FR> UnregisteredInstance<FR> {
547552
}
548553
}
549554

555+
pub trait SandboxCapabiliesHolder<'a> {
556+
type SupervisorFuncRef;
557+
type SC: SandboxCapabilities<SupervisorFuncRef = Self::SupervisorFuncRef> + 'a;
558+
559+
fn with_sandbox_capabilities<R, F: FnOnce(&mut Self::SC) -> R>(f: F) -> R;
560+
}
561+
550562
/// Instantiate a guest module and return it's index in the store.
551563
///
552564
/// The guest module's code is specified in `wasm`. Environment that will be available to
@@ -555,13 +567,17 @@ impl<FR> UnregisteredInstance<FR> {
555567
/// normally created by `sp_sandbox::Instance` primitive.
556568
///
557569
/// Returns uninitialized sandboxed module instance or an instantiation error.
558-
pub fn instantiate<'a, FE: SandboxCapabilities>(
559-
supervisor_externals: &mut FE,
570+
pub fn instantiate<'a, FE, SCH>(
571+
// supervisor_externals: &mut FE,
560572
dispatch_thunk: FE::SupervisorFuncRef,
561573
wasm: &[u8],
562574
guest_env: GuestEnvironment,
563575
state: u32,
564-
) -> std::result::Result<UnregisteredInstance<FE::SupervisorFuncRef>, InstantiationError> {
576+
) -> std::result::Result<UnregisteredInstance<FE::SupervisorFuncRef>, InstantiationError>
577+
where
578+
FE: SandboxCapabilities + 'a,
579+
SCH: SandboxCapabiliesHolder<'a, SupervisorFuncRef = FE::SupervisorFuncRef, SC = FE>,
580+
{
565581
let wasmi_module = Module::from_buffer(wasm).map_err(|_| InstantiationError::ModuleDecoding)?;
566582
let wasmi_instance = ModuleInstance::new(&wasmi_module, &guest_env.imports)
567583
.map_err(|_| InstantiationError::Instantiation)?;
@@ -580,11 +596,19 @@ pub fn instantiate<'a, FE: SandboxCapabilities>(
580596
.filter_map(|import| {
581597
if let wasmtime::ExternType::Func(func_ty) = import.ty() {
582598
Some(wasmtime::Extern::Func(wasmtime::Func::new(&wasmtime_store, func_ty,
583-
move |_, _, _| Err(wasmtime::Trap::new(format!(
584-
"Sandbox function stub",
585-
// func_ty.to_string(),
586-
// func_ty.name().to_string()
587-
)))
599+
move |_, _, _| {
600+
SCH::with_sandbox_capabilities(|sc| {
601+
// sc.invoke();
602+
});
603+
604+
Ok(())
605+
}
606+
607+
// Err(wasmtime::Trap::new(format!(
608+
// "Sandbox function stub",
609+
// // func_ty.to_string(),
610+
// // func_ty.name().to_string()
611+
// )))
588612
)))
589613
} else {
590614
None
@@ -604,18 +628,20 @@ pub fn instantiate<'a, FE: SandboxCapabilities>(
604628
guest_to_supervisor_mapping: guest_env.guest_to_supervisor_mapping,
605629
});
606630

607-
with_guest_externals(
608-
supervisor_externals,
609-
&sandbox_instance,
610-
state,
611-
|guest_externals| {
612-
wasmi_instance
613-
.run_start(guest_externals)
614-
.map_err(|_| InstantiationError::StartTrapped)
631+
SCH::with_sandbox_capabilities( |supervisor_externals| {
632+
with_guest_externals(
633+
supervisor_externals,
634+
&sandbox_instance,
635+
state,
636+
|guest_externals| {
637+
wasmi_instance
638+
.run_start(guest_externals)
639+
.map_err(|_| InstantiationError::StartTrapped)
615640

616-
// Note: no need to run start on wasmtime instance, since it's done automatically
617-
},
618-
)?;
641+
// Note: no need to run start on wasmtime instance, since it's done automatically
642+
},
643+
)
644+
})?;
619645

620646
Ok(UnregisteredInstance { sandbox_instance })
621647
}

client/executor/wasmi/src/lib.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ impl<'a> Sandbox for FunctionExecutor<'a> {
198198
.collect::<Vec<_>>();
199199

200200
let instance = self.sandbox_store.instance(instance_id).map_err(|e| e.to_string())?;
201-
let result = instance.invoke(export_name, &args, self, state);
201+
let result = instance.invoke(export_name, &args, state);
202202

203203
match result {
204204
Ok(None) => Ok(sandbox_primitives::ERR_OK),
@@ -242,8 +242,24 @@ impl<'a> Sandbox for FunctionExecutor<'a> {
242242
Err(_) => return Ok(sandbox_primitives::ERR_MODULE as u32),
243243
};
244244

245+
struct Adapter;
246+
247+
impl<'a> sandbox::SandboxCapabiliesHolder<'a> for Adapter {
248+
type SupervisorFuncRef = wasmi::FuncRef;
249+
type SC = FunctionExecutor<'static>;
250+
251+
fn with_sandbox_capabilities<R, F: FnOnce(&mut Self::SC) -> R>(f: F) -> R {
252+
todo!();
253+
254+
// FOO.with(|fe| {
255+
// let mut fe = fe.borrow_mut();
256+
// f(fe.deref_mut())
257+
// });
258+
}
259+
}
260+
245261
let instance_idx_or_err_code =
246-
match sandbox::instantiate(self, dispatch_thunk, wasm, guest_env, state)
262+
match sandbox::instantiate::<_, Adapter>(dispatch_thunk, wasm, guest_env, state)
247263
.map(|i| i.register(&mut self.sandbox_store))
248264
{
249265
Ok(instance_idx) => instance_idx,

client/executor/wasmtime/src/host.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use sc_executor_common::sandbox::{self, SandboxCapabilities, SupervisorFuncIndex
2828
use sp_core::sandbox as sandbox_primitives;
2929
use sp_wasm_interface::{FunctionContext, MemoryId, Pointer, Sandbox, WordSize};
3030
use wasmtime::{Func, Val};
31+
use sandbox::SandboxCapabiliesHolder;
3132

3233
/// Wrapper type for pointer to a Wasm table entry.
3334
///
@@ -75,6 +76,36 @@ impl HostState {
7576
/// a longer-living `HostState`.
7677
pub struct HostContext<'a>(&'a HostState);
7778

79+
scoped_tls::scoped_thread_local!(static HOST_CONTEXT: *mut HostContext<'_>);
80+
81+
impl<'a> SandboxCapabiliesHolder<'a> for HostContext<'a> {
82+
type SupervisorFuncRef = SupervisorFuncRef;
83+
type SC = HostContext<'static>;
84+
85+
fn with_sandbox_capabilities<R, F: FnOnce(&mut Self::SC) -> R>(f: F) -> R {
86+
use std::ops::DerefMut;
87+
88+
HOST_CONTEXT.with(|fe| {
89+
// Safe because of a limited scope in which the value exists
90+
let fe = unsafe { &mut **fe };
91+
92+
f(fe)
93+
})
94+
}
95+
}
96+
97+
impl<'a> HostContext<'a> {
98+
fn set_sandbox_capabilities<R, F: FnOnce() -> R>(&mut self, f: F) -> R {
99+
unsafe {
100+
// Erasing lifetime of `HostContext` to put it into scoped TLS. This is safe because
101+
// the pointer will never leave this scope and is semantically equivalent to `&'a mut`.
102+
let self_ptr: *mut HostContext<'static> = std::mem::transmute(self as *mut HostContext<'a>);
103+
104+
HOST_CONTEXT.set(&self_ptr, f)
105+
}
106+
}
107+
}
108+
78109
impl<'a> std::ops::Deref for HostContext<'a> {
79110
type Target = HostState;
80111
fn deref(&self) -> &HostState {
@@ -262,7 +293,20 @@ impl<'a> Sandbox for HostContext<'a> {
262293
.borrow()
263294
.instance(instance_id)
264295
.map_err(|e| e.to_string())?;
265-
let result = instance.invoke(export_name, &args, self, state);
296+
297+
let result = self.set_sandbox_capabilities(|| {
298+
instance.invoke(export_name, &args, state)
299+
});
300+
301+
// let result = unsafe {
302+
// // Erasing lifetime of `HostContext` to put it into scoped TLS. This is safe because
303+
// // the pointer will never leave this scope and is semantically equivalent to `&'a mut`.
304+
// let self_ptr: *mut HostContext<'static> = std::mem::transmute(self as *mut HostContext<'a>);
305+
306+
// HOST_CONTEXT.set(&self_ptr, || {
307+
// instance.invoke(export_name, &args, self, state)
308+
// })
309+
// };
266310

267311
match result {
268312
Ok(None) => Ok(sandbox_primitives::ERR_OK),
@@ -319,7 +363,7 @@ impl<'a> Sandbox for HostContext<'a> {
319363
};
320364

321365
let instance_idx_or_err_code =
322-
match sandbox::instantiate(self, dispatch_thunk, wasm, guest_env, state)
366+
match sandbox::instantiate::<_, Self>(dispatch_thunk, wasm, guest_env, state)
323367
.map(|i| i.register(&mut *self.sandbox_store.borrow_mut()))
324368
{
325369
Ok(instance_idx) => instance_idx,

0 commit comments

Comments
 (0)