Starts or resumes execution of `image`. Returns a `StopReason` indicating why execution stopped, which may be due to program termination, an exception, or a pending upcall that requires caller handling.
(&'a mut self, image: &'a Image)
| 441 | /// Returns a `StopReason` indicating why execution stopped, which may be due to program |
| 442 | /// termination, an exception, or a pending upcall that requires caller handling. |
| 443 | pub fn exec<'a>(&'a mut self, image: &'a Image) -> StopReason<'a> { |
| 444 | self.sync_upcalls(image); |
| 445 | |
| 446 | loop { |
| 447 | if self.pending_upcall.is_some() { |
| 448 | return StopReason::UpcallAsync(UpcallHandler { vm: self, image }); |
| 449 | } |
| 450 | |
| 451 | match self.context.exec(image, &mut self.heap) { |
| 452 | InternalStopReason::End(code) => { |
| 453 | self.park_at_eof(image); |
| 454 | return StopReason::End(code); |
| 455 | } |
| 456 | InternalStopReason::Eof => return StopReason::Eof, |
| 457 | InternalStopReason::Exception(pc, e) => { |
| 458 | let pos = image.debug_info.instrs[pc].linecol; |
| 459 | if !self.handle_exception(image, pc, pos, e.clone()) { |
| 460 | self.park_at_eof(image); |
| 461 | return StopReason::Exception(pos, e); |
| 462 | } |
| 463 | } |
| 464 | InternalStopReason::Upcall(index, first_reg, upcall_pc) => { |
| 465 | let (upcall, scope) = self.prepare_upcall(image, index, first_reg, upcall_pc); |
| 466 | let result = upcall.exec(scope); |
| 467 | if let Err(upcall_error) = self.handle_upcall_result(image, upcall_pc, result) { |
| 468 | let (pos, message) = upcall_error.parts(); |
| 469 | self.park_at_eof(image); |
| 470 | return StopReason::Exception(pos, message); |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | InternalStopReason::UpcallAsync(index, first_reg, upcall_pc) => { |
| 475 | self.pending_upcall = Some((index, first_reg, upcall_pc)); |
| 476 | return StopReason::UpcallAsync(UpcallHandler { vm: self, image }); |
| 477 | } |
| 478 | |
| 479 | InternalStopReason::Yield => return StopReason::Yield, |
| 480 | } |
| 481 | } |
| 482 | } |
| 483 | |
| 484 | /// Stops execution of `image` so that the next call to `exec` starts at EOF. |
| 485 | /// |