Skip to content

Commit 1776b42

Browse files
committed
Refactor linker to make it JS-compatible + fix other JS build errors
1 parent cb268e7 commit 1776b42

File tree

12 files changed

+209
-235
lines changed

12 files changed

+209
-235
lines changed

lib/wasix/src/runners/wasi.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -248,19 +248,27 @@ impl WasiRunner {
248248
}
249249

250250
fn ensure_tokio_runtime() -> Option<tokio::runtime::Runtime> {
251-
if tokio::runtime::Handle::try_current().is_ok() {
252-
return None;
253-
}
251+
#[cfg(feature = "sys-thread")]
252+
{
253+
if tokio::runtime::Handle::try_current().is_ok() {
254+
return None;
255+
}
254256

255-
let rt = tokio::runtime::Builder::new_multi_thread()
256-
.enable_all()
257-
.build()
258-
.expect(
259-
"Failed to build a multi-threaded tokio runtime. This is necessary \
257+
let rt = tokio::runtime::Builder::new_multi_thread()
258+
.enable_all()
259+
.build()
260+
.expect(
261+
"Failed to build a multi-threaded tokio runtime. This is necessary \
260262
for WASIX to work. You can provide a tokio runtime by building one \
261263
yourself and entering it before using WasiRunner.",
262-
);
263-
Some(rt)
264+
);
265+
Some(rt)
266+
}
267+
268+
#[cfg(not(feature = "sys-thread"))]
269+
{
270+
None
271+
}
264272
}
265273

266274
#[tracing::instrument(level = "debug", skip_all)]

lib/wasix/src/runtime/task_manager/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,8 @@ impl dyn VirtualTaskManager {
380380

381381
let snapshot = capture_store_snapshot(&mut store.as_store_mut());
382382
let env = ctx.data(&store);
383-
let handles = env
384-
.inner()
383+
let env_inner = env.inner();
384+
let handles = env_inner
385385
.static_module_instance_handles()
386386
.ok_or(WasiThreadError::Unsupported)?;
387387
let module = handles.module_clone();

lib/wasix/src/state/env.rs

Lines changed: 56 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -416,39 +416,42 @@ impl WasiEnv {
416416
update_layout: bool,
417417
call_initialize: bool,
418418
) -> Result<(Instance, WasiFunctionEnv), WasiThreadError> {
419-
let is_dl = super::linker::is_dynamically_linked(&module);
420-
421419
let pid = self.process.pid();
422420

423421
let mut store = store.as_store_mut();
424-
425422
let mut func_env = WasiFunctionEnv::new(&mut store, self);
426423

424+
let is_dl = super::linker::is_dynamically_linked(&module);
425+
if is_dl {
426+
// TODO: make stack size configurable
427+
// TODO: make linker support update_layout and call_initialize when we plan for threads
428+
match Linker::new(&module, &mut store, memory, &mut func_env, 8 * 1024 * 1024) {
429+
Ok((_, linked_module)) => {
430+
return Ok((linked_module.instance, func_env));
431+
}
432+
Err(e) => {
433+
tracing::error!(
434+
%pid,
435+
error = &e as &dyn std::error::Error,
436+
"Failed to link DL main module",
437+
);
438+
func_env
439+
.data(&store)
440+
.blocking_on_exit(Some(Errno::Noexec.into()));
441+
return Err(WasiThreadError::LinkError(Arc::new(e)));
442+
}
443+
}
444+
}
445+
427446
// Let's instantiate the module with the imports.
428447
let (mut import_object, instance_init_callback) =
429448
import_object_for_all_wasi_versions(&module, &mut store, &func_env.env);
430449

431-
let (linker, imported_memory) = if is_dl {
432-
// TODO: make stack size configurable
433-
let (linker, linked_module) = Linker::new_for_main_module(
434-
&module,
435-
&mut store,
436-
memory,
437-
&mut import_object,
438-
&func_env.env,
439-
8 * 1024 * 1024,
440-
)
441-
.map_err(|e| WasiThreadError::LinkError(Arc::new(e)))?;
442-
443-
(
444-
Some((linker, linked_module.stack_low, linked_module.stack_high)),
445-
Some(linked_module.memory),
446-
)
447-
} else if let Some(memory) = memory {
450+
let imported_memory = if let Some(memory) = memory {
448451
import_object.define("env", "memory", memory.clone());
449-
(None, Some(memory))
452+
Some(memory)
450453
} else {
451-
(None, None)
454+
None
452455
};
453456

454457
// Construct the instance.
@@ -467,38 +470,13 @@ impl WasiEnv {
467470
}
468471
};
469472

470-
let (linker, handles, stack_layout) = match (linker, imported_memory) {
471-
(Some((linker, low, high)), Some(memory)) => {
472-
let layout = WasiMemoryLayout {
473-
stack_lower: low,
474-
stack_upper: high,
475-
stack_size: high - low,
476-
guard_size: 0,
477-
};
478-
(
479-
Some(linker.clone()),
480-
WasiModuleTreeHandles::Dynamic {
481-
linker,
482-
main_module_instance_handles: WasiModuleInstanceHandles::new(
483-
memory,
484-
&store,
485-
instance.clone(),
486-
),
487-
},
488-
Some(layout),
489-
)
490-
}
491-
(Some(_), None) => unreachable!(),
492-
(None, Some(memory)) => (
493-
None,
494-
WasiModuleTreeHandles::Static(WasiModuleInstanceHandles::new(
495-
memory,
496-
&store,
497-
instance.clone(),
498-
)),
499-
None,
500-
),
501-
(None, None) => {
473+
let handles = match imported_memory {
474+
Some(memory) => WasiModuleTreeHandles::Static(WasiModuleInstanceHandles::new(
475+
memory,
476+
&store,
477+
instance.clone(),
478+
)),
479+
None => {
502480
let exported_memory = instance
503481
.exports
504482
.iter()
@@ -513,15 +491,11 @@ impl WasiEnv {
513491
.ok_or(WasiThreadError::ExportError(ExportError::Missing(
514492
"No imported or exported memory found".to_owned(),
515493
)))?;
516-
(
517-
None,
518-
WasiModuleTreeHandles::Static(WasiModuleInstanceHandles::new(
519-
exported_memory,
520-
&store,
521-
instance.clone(),
522-
)),
523-
None,
524-
)
494+
WasiModuleTreeHandles::Static(WasiModuleInstanceHandles::new(
495+
exported_memory,
496+
&store,
497+
instance.clone(),
498+
))
525499
}
526500
};
527501

@@ -530,7 +504,7 @@ impl WasiEnv {
530504
&mut store,
531505
instance.clone(),
532506
handles,
533-
stack_layout,
507+
None,
534508
update_layout,
535509
) {
536510
tracing::error!(
@@ -544,42 +518,11 @@ impl WasiEnv {
544518
return Err(WasiThreadError::ExportError(err));
545519
}
546520

547-
if let Some(linker) = linker {
548-
// FIXME: The linker calls side modules' init function regardless of the value of
549-
// call_initialize. Currently, there are no scenarios where call_initialize is
550-
// false and we're loading a DL module, since such scenarios (threading, asyncify,
551-
// etc.) are not supported in the presence of DL.
552-
linker
553-
.initialize(&mut store, instance.clone())
554-
.map_err(|e| match e {
555-
super::linker::InitializeError::LinkError(e) => {
556-
WasiThreadError::LinkError(Arc::new(e))
557-
}
558-
super::linker::InitializeError::AlreadyInitialized => {
559-
panic!("Internal error: linker can't have been initialized before")
560-
}
561-
})?;
562-
}
563-
564521
// Run initializers.
565522
instance_init_callback(&instance, &store).unwrap();
566523

567524
// If this module exports an _initialize function, run that first.
568525
if call_initialize {
569-
// This function is exported from PIE executables, and needs to be run before calling
570-
// _initialize or _start. More info:
571-
// https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
572-
if let Ok(apply_data_relocs) = instance.exports.get_function("__wasm_apply_data_relocs")
573-
{
574-
if let Err(err) = crate::run_wasi_func_start(apply_data_relocs, &mut store) {
575-
func_env
576-
.data(&store)
577-
.blocking_on_exit(Some(Errno::Noexec.into()));
578-
return Err(WasiThreadError::InitFailed(Arc::new(anyhow::Error::from(
579-
err,
580-
))));
581-
}
582-
}
583526
if let Ok(initialize) = instance.exports.get_function("_initialize") {
584527
if let Err(err) = crate::run_wasi_func_start(initialize, &mut store) {
585528
func_env
@@ -627,10 +570,10 @@ impl WasiEnv {
627570
// If a signal handler has never been set then we need to handle signals
628571
// differently
629572
let env = ctx.data();
630-
let inner = env
573+
let env_inner = env
631574
.try_inner()
632-
.ok_or_else(|| WasiError::Exit(Errno::Fault.into()))?
633-
.main_module_instance_handles();
575+
.ok_or_else(|| WasiError::Exit(Errno::Fault.into()))?;
576+
let inner = env_inner.main_module_instance_handles();
634577
if !inner.signal_set {
635578
let signals = env.thread.pop_signals();
636579
if !signals.is_empty() {
@@ -664,10 +607,10 @@ impl WasiEnv {
664607
// If a signal handler has never been set then we need to handle signals
665608
// differently
666609
let env = ctx.data();
667-
let inner = env
610+
let env_inner = env
668611
.try_inner()
669-
.ok_or_else(|| WasiError::Exit(Errno::Fault.into()))?
670-
.main_module_instance_handles();
612+
.ok_or_else(|| WasiError::Exit(Errno::Fault.into()))?;
613+
let inner = env_inner.main_module_instance_handles();
671614
if !inner.signal_set {
672615
return Ok(Ok(false));
673616
}
@@ -689,10 +632,10 @@ impl WasiEnv {
689632
mut signals: Vec<Signal>,
690633
) -> Result<bool, WasiError> {
691634
let env = ctx.data();
692-
let inner = env
635+
let env_inner = env
693636
.try_inner()
694-
.ok_or_else(|| WasiError::Exit(Errno::Fault.into()))?
695-
.main_module_instance_handles();
637+
.ok_or_else(|| WasiError::Exit(Errno::Fault.into()))?;
638+
let inner = env_inner.main_module_instance_handles();
696639
if let Some(handler) = inner.signal.clone() {
697640
// We might also have signals that trigger on timers
698641
let mut now = 0;
@@ -847,17 +790,20 @@ impl WasiEnv {
847790
/// Tries to clone the instance from this environment, but only if it's a static
848791
/// module, since dynamically linked modules are made up of multiple instances.
849792
pub fn try_clone_instance(&self) -> Option<Instance> {
850-
self.inner
851-
.get()
852-
.and_then(|i| i.static_module_instance_handles())
853-
.map(|i| i.instance.clone())
793+
let guard = self.inner.get();
794+
match guard {
795+
Some(guard) => match guard.static_module_instance_handles() {
796+
Some(instance) => Some(instance.instance.clone()),
797+
None => None,
798+
},
799+
None => None,
800+
}
854801
}
855802

856803
/// Providers safe access to the memory
857804
/// (it must be initialized before it can be used)
858805
pub fn try_memory(&self) -> Option<WasiInstanceGuardMemory<'_>> {
859-
self.try_inner()
860-
.map(|i| i.main_module_instance_handles().memory())
806+
self.try_inner().map(|i| i.memory())
861807
}
862808

863809
/// Providers safe access to the memory

lib/wasix/src/state/handles/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,4 +247,29 @@ impl WasiModuleTreeHandles {
247247
_ => Err(()),
248248
}
249249
}
250+
251+
/// Providers safe access to the memory
252+
/// (it must be initialized before it can be used)
253+
pub fn memory_view<'a>(&'a self, store: &'a (impl AsStoreRef + ?Sized)) -> MemoryView<'a> {
254+
self.main_module_instance_handles().memory.view(store)
255+
}
256+
257+
/// Providers safe access to the memory
258+
/// (it must be initialized before it can be used)
259+
pub fn memory(&self) -> &Memory {
260+
&self.main_module_instance_handles().memory
261+
}
262+
263+
/// Copy the lazy reference so that when it's initialized during the
264+
/// export phase, all the other references get a copy of it
265+
pub fn memory_clone(&self) -> Memory {
266+
self.main_module_instance_handles().memory.clone()
267+
}
268+
269+
pub fn linker(&self) -> Option<&Linker> {
270+
match self {
271+
Self::Static(_) => None,
272+
Self::Dynamic { linker, .. } => Some(linker),
273+
}
274+
}
250275
}

lib/wasix/src/state/handles/thread_local.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ impl<'a> Deref for WasiInstanceGuardMemory<'a> {
159159
}
160160
impl<'a> WasiInstanceGuard<'a> {
161161
pub fn memory(self) -> WasiInstanceGuardMemory<'a> {
162-
let borrow: &Memory = &self.main_module_instance_handles().memory;
162+
let borrow: &Memory = (*self).memory();
163163
let borrow: &'a Memory = unsafe { std::mem::transmute(borrow) };
164164
WasiInstanceGuardMemory {
165165
borrow,

0 commit comments

Comments
 (0)