Skip to content

Commit

Permalink
web: Updates for futures rework
Browse files Browse the repository at this point in the history
  • Loading branch information
encounter committed Aug 7, 2024
1 parent 5c92c7d commit 6822158
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ fn main() -> anyhow::Result<ExitCode> {

#[cfg(feature = "x86-emu")]
{
let millis = start.elapsed().as_millis() as u64;
let millis = start.elapsed().as_millis() as usize;
if millis > 0 {
eprintln!(
"{} instrs in {} ms: {}m/s",
Expand Down
4 changes: 1 addition & 3 deletions web/emulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class Emulator extends JsHost {
const endTime = performance.now();
const endSteps = this.emu.instr_count;

const steps = Number(endSteps - startSteps);
const steps = endSteps - startSteps;
const deltaTime = endTime - startTime;
if (steps > 1000 && deltaTime >= 1) { // only update if we ran enough instructions to get a good measurement
const instrPerMs = steps / deltaTime;
Expand Down Expand Up @@ -106,8 +106,6 @@ export class Emulator extends JsHost {
return false;
}
case wasm.CPUState.Blocked:
// Return control to the browser event loop.
return false;
case wasm.CPUState.Error:
case wasm.CPUState.Exit:
this.emuHost.onStopped();
Expand Down
1 change: 1 addition & 0 deletions web/glue/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ x86 = { workspace = true, features = ["wasm"] }

anyhow = "1.0"
chrono = "0.4.38"
futures = "0.3.30"
js-sys = "0.3.69"
serde = "1.0"
serde_json = "1.0"
Expand Down
58 changes: 50 additions & 8 deletions web/glue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,24 @@ mod host;
mod log;

use crate::host::JsHost;
use std::task::{Context, Poll};
use wasm_bindgen::prelude::*;

pub type JsResult<T> = Result<T, JsError>;
fn err_from_anyhow(err: anyhow::Error) -> JsError {
JsError::new(&err.to_string())
}

struct AsyncShimCall {
shim: &'static win32::shims::Shim,
future: win32::shims::BoxFuture<u32>,
}

#[wasm_bindgen]
pub struct Emulator {
machine: win32::Machine,
shim_calls: Vec<AsyncShimCall>,
ctx: Context<'static>,
}

#[wasm_bindgen]
Expand Down Expand Up @@ -62,7 +70,7 @@ impl Emulator {
}

#[wasm_bindgen(getter)]
pub fn instr_count(&self) -> u64 {
pub fn instr_count(&self) -> usize {
self.machine.emu.x86.instr_count
}

Expand All @@ -80,10 +88,23 @@ impl Emulator {
if count == 1 {
return match self.machine.run(1) {
win32::StopReason::None => Ok(CPUState::Running),
win32::StopReason::Blocked => Ok(CPUState::Blocked),
win32::StopReason::Blocked => {
// Poll the last future.
let shim_call = self.shim_calls.last_mut().unwrap();
match shim_call.future.as_mut().poll(&mut self.ctx) {
Poll::Ready(ret) => {
self.machine.finish_shim_call(shim_call.shim, ret);
self.shim_calls.pop();
}
Poll::Pending => {}
}
Ok(CPUState::Running)
}
win32::StopReason::Breakpoint { .. } => Ok(CPUState::DebugBreak),
win32::StopReason::ShimCall(shim) => {
self.machine.call_shim(shim);
if let Some(future) = self.machine.call_shim(shim) {
self.shim_calls.push(AsyncShimCall { shim, future });
}
Ok(CPUState::Running)
}
win32::StopReason::Error { message, .. } => Err(JsError::new(&message)),
Expand All @@ -93,14 +114,31 @@ impl Emulator {
// Note that instr_count overflows at 4b, but we don't expect to run
// 4b instructions in a single run() invocation.
let start = self.machine.emu.x86.instr_count;
while self.machine.emu.x86.instr_count.wrapping_sub(start) < count as u64 {
while self.machine.emu.x86.instr_count.wrapping_sub(start) < count {
match self.machine.run(0) {
win32::StopReason::None => {}
win32::StopReason::Blocked => break,
win32::StopReason::Blocked => {
// Poll the last future.
let shim_call = self.shim_calls.last_mut().unwrap();
match shim_call.future.as_mut().poll(&mut self.ctx) {
Poll::Ready(ret) => {
self.machine.finish_shim_call(shim_call.shim, ret);
self.shim_calls.pop();
// Continue running after the shim call completes.
}
Poll::Pending => {
// Return control to the event loop to allow the future to progress.
break;
}
}
}
win32::StopReason::Breakpoint { .. } => return Ok(CPUState::DebugBreak),
win32::StopReason::ShimCall(shim) => {
self.machine.call_shim(shim);
break;
if let Some(future) = self.machine.call_shim(shim) {
self.shim_calls.push(AsyncShimCall { shim, future });
// Return control to the event loop to allow the future to progress.
break;
}
}
win32::StopReason::Error { message, .. } => return Err(JsError::new(&message)),
win32::StopReason::Exit { .. } => return Ok(CPUState::Exit),
Expand Down Expand Up @@ -140,5 +178,9 @@ impl Emulator {
pub fn new_emulator(host: JsHost, cmdline: String) -> Emulator {
log::init(log::JsLogger::unchecked_from_js(host.clone()));
let machine = win32::Machine::new(Box::new(host), cmdline);
Emulator { machine }
Emulator {
machine,
shim_calls: Default::default(),
ctx: Context::from_waker(futures::task::noop_waker_ref()),
}
}
2 changes: 1 addition & 1 deletion x86/src/x86.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ pub struct X86 {
pub cur_cpu: usize,

/// Total number of instructions executed.
pub instr_count: u64,
pub instr_count: usize,

pub icache: InstrCache,
}
Expand Down

0 comments on commit 6822158

Please sign in to comment.