Skip to content

Commit

Permalink
Update titan to drop Recovery
Browse files Browse the repository at this point in the history
  • Loading branch information
1whatleytay committed Sep 11, 2024
1 parent a3388fa commit 4f3634c
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 67 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"dev": "yarn wasm && vite",
"build": "yarn wasm && vue-tsc --noEmit && vite build",
"preview": "vite preview",
"tauri": "tauri"
"tauri": "tauri",
"cargo-bump": "cd src-backend && cargo update && cd ../src-tauri && cargo update && cd ../src-wasm && cargo update"
},
"dependencies": {
"@heroicons/vue": "^2.0.13",
Expand Down
6 changes: 3 additions & 3 deletions src-backend/Cargo.lock

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

4 changes: 0 additions & 4 deletions src-backend/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ impl ResumeMode {
fn from_executor<Mem: Memory>(value: ExecutorMode, state: &State<Mem>) -> Self {
match value {
ExecutorMode::Running => ResumeMode::Running,
ExecutorMode::Recovered => ResumeMode::Breakpoint,
ExecutorMode::Invalid(error) => ResumeMode::Invalid {
message: format_error(error, state)
},
Expand Down Expand Up @@ -200,12 +199,9 @@ impl<Mem: Memory + Send, Track: Tracker<Mem> + Send> ExecutionDevice for Executi
let state = self.delegate.clone();
let finished_pcs = self.finished_pcs.clone();

log::info!("Resuming with batch options: {:?}", options.batch);

if let Some(breakpoints) = options.breakpoints {
let breakpoints_set = HashSet::from_iter(breakpoints.iter().copied());

log::info!("Overriding breakpoints: {:?}", breakpoints_set);
debugger.set_breakpoints(breakpoints_set);
}

Expand Down
47 changes: 17 additions & 30 deletions src-backend/src/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use titan::cpu::error::Error::{CpuSyscall, CpuTrap};
use titan::cpu::state::Registers;
use titan::cpu::Memory;
use titan::execution::executor::DebugFrame;
use titan::execution::executor::ExecutorMode::{Invalid, Recovered};
use titan::execution::executor::ExecutorMode::{Invalid,};
use titan::execution::Executor;
use titan::execution::trackers::Tracker;
use futures::{FutureExt, select};
Expand Down Expand Up @@ -782,54 +782,44 @@ impl SyscallDelegate {
&self,
debugger: &Executor<Mem, Track>,
frame: DebugFrame,
) -> (Option<DebugFrame>, Option<SyscallResult>) {
) -> (Option<DebugFrame>, Option<SyscallResult>, bool) {
match frame.mode {
Invalid(CpuSyscall) => {
// $v0
let code = debugger.with_state(|s| s.registers.line[V0_REG]);
let result = self.dispatch(debugger, code).await;

(
match result {
Completed => {
debugger.syscall_handled();

None
}
_ => Some(frame),
},
Some(result),
)
match result {
Completed => {
debugger.syscall_handled();

(None, Some(result), true)
}
_ => (Some(frame), Some(result), false),
}
}
_ => (Some(frame), None),
_ => (Some(frame), None, false),
}
}

// A syscall will interrupt a batch!
pub async fn run_batch<Mem: Memory, Track: Tracker<Mem>>(
&self, debugger: &Executor<Mem, Track>, batch: usize, should_skip_first: bool, allow_interrupt: bool
) -> Option<(DebugFrame, Option<SyscallResult>)> {
log::info!("Running batch (size: {batch}, should_skip_first: {should_skip_first}, allow_interrupt: {allow_interrupt})");

if !debugger.run_batched(batch, should_skip_first, allow_interrupt).interrupted {
return None // no interruption, batch completed successfully
}

let frame_in = debugger.frame();

let (frame, result) = self.handle_frame(debugger, frame_in).await;
let (frame, result, recovered) = self.handle_frame(debugger, frame_in).await;

if let Some(frame) = frame {
return Some((frame, result));
}

// Need to re-check.
let frame = debugger.frame();

log::info!("Resulting debugger frame handled with output mode: {:?}, result: {:?}", frame.mode, result);

if frame.mode != Recovered {
return Some((frame, None))
if !recovered {
return Some((debugger.frame(), None))
}

None
Expand All @@ -840,17 +830,14 @@ impl SyscallDelegate {
) -> (DebugFrame, Option<SyscallResult>) {
loop {
let frame = debugger.run(should_skip_first);
let (frame, result) = self.handle_frame(debugger, frame).await;
let (frame, result, recovered) = self.handle_frame(debugger, frame).await;

if let Some(frame) = frame {
return (frame, result);
}

// Need to re-check.
let frame = debugger.frame();

if frame.mode != Recovered {
return (frame, None);
if !recovered {
return (debugger.frame(), None);
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions src-tauri/Cargo.lock

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

6 changes: 3 additions & 3 deletions src-wasm/Cargo.lock

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

33 changes: 17 additions & 16 deletions src-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod midi;
mod time;
mod events;

use std::cell::RefCell;
use std::collections::HashSet;
use std::io::Cursor;
use std::rc::Rc;
Expand Down Expand Up @@ -82,7 +83,7 @@ pub fn detailed_disassemble(bytes: Vec<u8>) -> Result<JsValue, String> {
#[derive(Default)]
pub struct Runner {
display: FlushDisplayBody,
device: Option<Rc<dyn RewindableDevice>>
device: RefCell<Option<Rc<dyn RewindableDevice>>>
}

impl Runner {
Expand Down Expand Up @@ -142,8 +143,8 @@ impl Runner {
Runner::default()
}

pub fn set_breakpoints(&mut self, breakpoints: &[u32]) {
if let Some(device) = &mut self.device {
pub fn set_breakpoints(&self, breakpoints: &[u32]) {
if let Some(device) = self.device.borrow() {
device.set_breakpoints(HashSet::<u32>::from_iter(breakpoints.iter().copied()))
}
}
Expand Down Expand Up @@ -265,26 +266,26 @@ impl Runner {
serde_wasm_bindgen::to_value(&result).unwrap()
}

pub fn last_pc(&mut self) -> Option<u32> {
pub fn last_pc(&self) -> Option<u32> {
self.device.as_ref().and_then(|device| device.last_pc())
}

pub fn read_bytes(&mut self, address: u32, count: u32) -> JsValue {
pub fn read_bytes(&self, address: u32, count: u32) -> JsValue {
let result = self.device
.as_ref()
.and_then(|device| device.read_bytes(address, count));

serde_wasm_bindgen::to_value(&result).unwrap()
}

pub fn write_bytes(&mut self, address: u32, bytes: Vec<u8>) {
if let Some(device) = &mut self.device {
pub fn write_bytes(&self, address: u32, bytes: Vec<u8>) {
if let Some(device) = &self.device {
device.write_bytes(address, bytes)
}
}

pub fn set_register(&mut self, register: u32, value: u32) {
if let Some(device) = &mut self.device {
pub fn set_register(&self, register: u32, value: u32) {
if let Some(device) = &self.device {
device.write_register(register, value)
}
}
Expand Down Expand Up @@ -315,8 +316,8 @@ impl Runner {
}
}

pub async fn resume(&mut self, batch_size: usize, breakpoints: Option<Vec<u32>>, first_batch: bool, is_step: bool) -> JsValue {
let Some(device) = &mut self.device else {
pub async fn resume(&self, batch_size: usize, breakpoints: Option<Vec<u32>>, first_batch: bool, is_step: bool) -> JsValue {
let Some(device) = &self.device else {
return JsValue::NULL
};

Expand All @@ -334,16 +335,16 @@ impl Runner {
serde_wasm_bindgen::to_value(&result.ok()).unwrap()
}

pub fn pause(&mut self) {
let Some(device) = &mut self.device else {
pub fn pause(&self) {
let Some(device) = &self.device else {
return
};

device.pause()
}

pub fn stop(&mut self) {
let Some(device) = &mut self.device else {
pub fn stop(&self) {
let Some(device) = &self.device else {
return
};

Expand All @@ -352,7 +353,7 @@ impl Runner {
self.device = None
}

pub fn rewind(&mut self, count: u32) -> JsValue {
pub fn rewind(&self, count: u32) -> JsValue {
let Some(device) = &mut self.device else {
return JsValue::NULL
};
Expand Down
22 changes: 19 additions & 3 deletions src/utils/mips/wasm-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import {
MessageResponse,
PostInputData,
PostKeyData,
ReadBytesData, ReadDisplayData,
ResumeData, RewindData,
ReadBytesData,
ReadDisplayData,
ResumeData,
RewindData,
SetBreakpointsData,
SetRegisterData,
WriteBytesData
Expand Down Expand Up @@ -87,6 +89,20 @@ function configureAsm({ text, timeTravel }: ConfigureAsmData): AssemblerResult {
return runner.configure_asm(text, timeTravel)
}

// Thanks to Milo
// https://github.com/facebook/react/blob/66cf2cfc8a8c4b09d2b783fd7302ae6b24150935/packages/scheduler/src/forks/Scheduler.js#L534-L540
const channel = new MessageChannel()
const port = channel.port2
let currentResolve: (() => void) | null = null
channel.port1.onmessage = () => currentResolve!()

function awaitMacrotaskFast(): Promise<void> {
return new Promise<void>(resolve => {
currentResolve = resolve
port.postMessage(null)
});
}

async function resume({ count, breakpoints }: ResumeData): Promise<ExecutionResult | null> {
const batchSize = 1200 // worth adjusting this batch size

Expand Down Expand Up @@ -115,7 +131,7 @@ async function resume({ count, breakpoints }: ResumeData): Promise<ExecutionResu

instructionsExecuted += batchSize

await new Promise<void>(resolve => setTimeout(resolve, 0))
await awaitMacrotaskFast()
}

return result
Expand Down

0 comments on commit 4f3634c

Please sign in to comment.