-
Notifications
You must be signed in to change notification settings - Fork 27
Pausing execution of interpreter #687
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
4e5af2f
5e60115
3eb6b3d
08a9d41
f986ed4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,6 +15,11 @@ | |||||||||
| // TODO: Some toctou could be used instead of panic. | ||||||||||
| use alloc::vec; | ||||||||||
| use alloc::vec::Vec; | ||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| use core::sync::atomic::Ordering::Relaxed; | ||||||||||
|
|
||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| use portable_atomic::AtomicBool; | ||||||||||
|
|
||||||||||
| use crate::error::*; | ||||||||||
| use crate::module::*; | ||||||||||
|
|
@@ -58,6 +63,9 @@ pub struct Store<'m> { | |||||||||
| // functions in `funcs` is stored to limit normal linking to that part. | ||||||||||
| func_default: Option<(&'m str, usize)>, | ||||||||||
| threads: Vec<Continuation<'m>>, | ||||||||||
|
|
||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| interrupt: Option<&'m AtomicBool>, | ||||||||||
| } | ||||||||||
|
|
||||||||||
| #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] | ||||||||||
|
|
@@ -99,6 +107,8 @@ impl Default for Store<'_> { | |||||||||
| funcs: vec![], | ||||||||||
| func_default: None, | ||||||||||
| threads: vec![], | ||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| interrupt: None, | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
@@ -195,9 +205,24 @@ impl<'m> Store<'m> { | |||||||||
| let mut parser = self.insts[inst_id].module.func(ptr.index()); | ||||||||||
| let mut locals = Vec::new(); | ||||||||||
| append_locals(&mut parser, &mut locals); | ||||||||||
| let thread = Thread::new(parser, Frame::new(inst_id, 0, &[], locals)); | ||||||||||
| let thread = Thread::new( | ||||||||||
| parser, | ||||||||||
| Frame::new(inst_id, 0, &[], locals), | ||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| self.interrupt, | ||||||||||
|
||||||||||
| ); | ||||||||||
|
|
||||||||||
| // Disable interrupts for the start section. | ||||||||||
|
||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| let interrupt = self.interrupt; | ||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| self.set_interrupt(None); | ||||||||||
|
|
||||||||||
| let result = thread.run(self)?; | ||||||||||
| assert!(matches!(result, RunResult::Done(x) if x.is_empty())); | ||||||||||
|
|
||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| self.set_interrupt(interrupt); | ||||||||||
| } | ||||||||||
| Ok(InstId { store_id: self.id, inst_id }) | ||||||||||
| } | ||||||||||
|
|
@@ -225,7 +250,13 @@ impl<'m> Store<'m> { | |||||||||
| let mut locals = args; | ||||||||||
| append_locals(&mut parser, &mut locals); | ||||||||||
| let frame = Frame::new(inst_id, t.results.len(), &[], locals); | ||||||||||
| Thread::new(parser, frame).run(self) | ||||||||||
| Thread::new( | ||||||||||
| parser, | ||||||||||
| frame, | ||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| self.interrupt, | ||||||||||
| ) | ||||||||||
| .run(self) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// Returns the value of a global of an instance. | ||||||||||
|
|
@@ -303,6 +334,11 @@ impl<'m> Store<'m> { | |||||||||
| Some(Call { store: self }) | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| pub fn set_interrupt(&mut self, interrupt: Option<&'m AtomicBool>) { | ||||||||||
| self.interrupt = interrupt; | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| impl<'a, 'm> Call<'a, 'm> { | ||||||||||
|
|
@@ -339,6 +375,12 @@ impl<'a, 'm> Call<'a, 'm> { | |||||||||
| thread.run(self.store) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Returns if this call is due to an interrupt. | ||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| pub fn is_interrupt(&self) -> bool { | ||||||||||
| self.cont().interrupted | ||||||||||
| } | ||||||||||
|
|
||||||||||
| fn cont(&self) -> &Continuation { | ||||||||||
| self.store.threads.last().unwrap() | ||||||||||
| } | ||||||||||
|
|
@@ -460,6 +502,8 @@ struct Instance<'m> { | |||||||||
| struct Thread<'m> { | ||||||||||
| parser: Parser<'m>, | ||||||||||
| frames: Vec<Frame<'m>>, | ||||||||||
| #[cfg(feature = "interrupt")] | ||||||||||
| interrupt: Option<&'m AtomicBool>, | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// Runtime result. | ||||||||||
|
|
@@ -470,6 +514,10 @@ pub enum RunResult<'a, 'm> { | |||||||||
|
|
||||||||||
| /// Execution is calling into the host. | ||||||||||
| Host(Call<'a, 'm>), | ||||||||||
|
|
||||||||||
| // Execution was interrupted by the host. | ||||||||||
|
||||||||||
| // Execution was interrupted by the host. | |
| /// Execution was interrupted by the host. |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's call this unbounded_continue, such that it doesn't mention interrupt.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if self.interrupt.is_some_and(|interrupt| { | |
| interrupt.compare_exchange_weak(true, false, Relaxed, Relaxed).is_ok() | |
| }) { | |
| if self.interrupt.is_some_and(|x|x.swap(false, Relaxed)) { |
resulknad marked this conversation as resolved.
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| ;; Use `wat2wasm infinite_loop.wat` to regenerate `.wasm`. | ||
| (module | ||
| (import "env" "count" (func $count (result i32))) | ||
|
|
||
| (memory (export "memory") 1) | ||
| (func (export "loopforever") | ||
| (local i32 i32) | ||
| (loop | ||
| (local.set 0 (call $count)) | ||
| (local.set 1 (i32.const 1)) | ||
| (block | ||
| (loop | ||
| (br_if 1 (i32.gt_u (local.get 1) (local.get 0))) | ||
| (local.set 1 (i32.add (local.get 1) (i32.const 1))) | ||
| (br 0) | ||
| ) | ||
| ) | ||
| (br 0) | ||
| ) | ||
| ) | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit