Skip to content

Commit

Permalink
Refactor.
Browse files Browse the repository at this point in the history
  • Loading branch information
sisshiki1969 committed Jul 9, 2023
1 parent 4c32058 commit b173522
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 118 deletions.
119 changes: 106 additions & 13 deletions monoruby/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,14 +237,6 @@ impl Executor {
self.temp_stack.len()
}

pub fn fiber_state(&self) -> FiberState {
match self.rsp_save {
None => FiberState::Created,
Some(p) if p.as_ptr() as i64 == -1 => FiberState::Terminated,
_ => FiberState::Suspended,
}
}

fn temp_push(&mut self, val: Value) {
self.temp_stack.push(val);
}
Expand All @@ -264,6 +256,111 @@ impl Executor {
}
}

//
// handling fiber.
//
impl Executor {
pub fn fiber_state(&self) -> FiberState {
match self.rsp_save {
None => FiberState::Created,
Some(p) if p.as_ptr() as i64 == -1 => FiberState::Terminated,
_ => FiberState::Suspended,
}
}

pub fn save_rsp(&mut self, rsp: *mut u8) {
self.rsp_save = Some(std::ptr::NonNull::new(rsp).unwrap());
}

fn invoke_fiber(
&mut self,
globals: &mut Globals,
fiber: &mut FiberInner,
arg: Arg,
len: usize,
) -> Result<Value> {
match (globals.codegen.fiber_invoker)(
self,
globals,
fiber.block_data(),
fiber.handle(),
arg.as_ptr(),
len,
) {
Some(val) => Ok(val),
None => Err(fiber.take_error()),
}
}

fn resume_fiber(&mut self, fiber: &mut FiberInner, val: Value) -> Result<Value> {
match resume_fiber(self, fiber.handle(), val) {
Some(val) => Ok(val),
None => Err(fiber.take_error()),
}
}

fn yield_fiber(&mut self, val: Value) -> Result<Value> {
match yield_fiber(self as _, val) {
Some(res) => Ok(res),
None => Err(unsafe { self.parent_fiber.unwrap().as_mut().take_error() }),
}
}
}

#[cfg(not(tarpaulin_include))]
#[naked]
extern "C" fn resume_fiber(vm: *mut Executor, child: *mut Executor, val: Value) -> Option<Value> {
unsafe {
std::arch::asm!(
"push r15",
"push r14",
"push r13",
"push r12",
"push rbx",
"push rbp",
"mov [rdi + 16], rsp", // [vm.rsp_save] <- rsp
"mov rsp, [rsi + 16]", // rsp <- [child_vm.rsp_save]
"mov [rsi + 24], rdi", // [child_vm.parent_fiber] <- vm
"pop rbp",
"pop rbx",
"pop r12",
"pop r13",
"pop r14",
"pop r15",
"mov rax, rdx",
"ret",
options(noreturn)
);
}
}

#[cfg(not(tarpaulin_include))]
#[naked]
extern "C" fn yield_fiber(vm: *mut Executor, val: Value) -> Option<Value> {
unsafe {
std::arch::asm!(
"push r15",
"push r14",
"push r13",
"push r12",
"push rbx",
"push rbp",
"mov [rdi + 16], rsp", // [vm.rsp_save] <- rsp
"mov rdi, [rdi + 24]", // rdi <- [vm.parent_fiber]
"mov rsp, [rdi + 16]", // rsp <- [parent.rsp_save]
"pop rbp",
"pop rbx",
"pop r12",
"pop r13",
"pop r14",
"pop r15",
"mov rax, rsi",
"ret",
options(noreturn)
);
}
}

impl Executor {
///
/// Execute top level method.
Expand All @@ -279,11 +376,7 @@ impl Executor {
res.ok_or_else(|| self.take_error())
}

pub(super) fn get_block_data(
&self,
globals: &mut Globals,
block_handler: BlockHandler,
) -> BlockData {
pub fn get_block_data(&self, globals: &mut Globals, block_handler: BlockHandler) -> BlockData {
if let Some((func_id, idx)) = block_handler.try_proxy() {
let mut cfp = self.cfp();
for _ in 0..idx {
Expand Down
4 changes: 4 additions & 0 deletions monoruby/src/executor/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ impl std::ops::Index<usize> for Arg {
}

impl Arg {
pub fn as_ptr(&self) -> *const Value {
self.0
}

pub fn to_vec(&self, len: usize) -> Vec<Value> {
if len == 0 {
return vec![];
Expand Down
103 changes: 10 additions & 93 deletions monoruby/src/executor/builtins/fiber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,9 @@ fn fiber_yield(
} else {
Value::array_from_iter(arg.iter(len))
};
match yield_fiber(vm as _, val) {
Some(res) => Ok(res),
None => Err(unsafe { vm.parent_fiber.unwrap().as_mut().take_error() }),
}
vm.yield_fiber(val)
}

const FIBER_STACK_SIZE: usize = 8192 * 8;

///
/// ### Fiber#resume
///
Expand All @@ -78,36 +73,16 @@ fn resume(
arg: Arg,
len: usize,
) -> Result<Value> {
use std::alloc::*;
let self_val = lfp.self_val();
let FiberInner {
mut handle,
block_data,
..
} = self_val.as_fiber();
let res = match unsafe { handle.as_ref().fiber_state() } {
let mut self_val = lfp.self_val();
let fiber = self_val.as_fiber_mut();
match fiber.state() {
FiberState::Created => {
let layout = Layout::from_size_align(FIBER_STACK_SIZE, 4096).unwrap();
unsafe {
let stack_bottom = alloc(layout);
libc::mprotect(stack_bottom as _, 4096, libc::PROT_NONE);
let stack_top = stack_bottom.add(FIBER_STACK_SIZE);
handle.as_mut().rsp_save = Some(std::ptr::NonNull::new(stack_top).unwrap());
}
(globals.codegen.fiber_invoker)(
vm,
globals,
block_data as _,
handle.as_ptr(),
arg.0,
len,
)
}
FiberState::Terminated => {
return Err(MonorubyErr::fibererr(
"attempt to resume a terminated fiber".to_string(),
))
fiber.init();
vm.invoke_fiber(globals, fiber, arg, len)
}
FiberState::Terminated => Err(MonorubyErr::fibererr(
"attempt to resume a terminated fiber".to_string(),
)),
FiberState::Suspended => {
let val = if len == 0 {
Value::nil()
Expand All @@ -116,66 +91,8 @@ fn resume(
} else {
Value::array_from_iter(arg.iter(len))
};
resume_fiber(vm as _, handle.as_ptr(), val)
vm.resume_fiber(fiber, val)
}
};
match res {
Some(val) => Ok(val),
None => Err(unsafe { handle.as_mut().take_error() }),
}
}

#[cfg(not(tarpaulin_include))]
#[naked]
extern "C" fn resume_fiber(vm: *mut Executor, child: *mut Executor, val: Value) -> Option<Value> {
unsafe {
std::arch::asm!(
"push r15",
"push r14",
"push r13",
"push r12",
"push rbx",
"push rbp",
"mov [rdi + 16], rsp", // [vm.rsp_save] <- rsp
"mov rsp, [rsi + 16]", // rsp <- [child_vm.rsp_save]
"mov [rsi + 24], rdi", // [child_vm.parent_fiber] <- vm
"pop rbp",
"pop rbx",
"pop r12",
"pop r13",
"pop r14",
"pop r15",
"mov rax, rdx",
"ret",
options(noreturn)
);
}
}

#[cfg(not(tarpaulin_include))]
#[naked]
extern "C" fn yield_fiber(vm: *mut Executor, val: Value) -> Option<Value> {
unsafe {
std::arch::asm!(
"push r15",
"push r14",
"push r13",
"push r12",
"push rbx",
"push rbp",
"mov [rdi + 16], rsp", // [vm.rsp_save] <- rsp
"mov rdi, [rdi + 24]", // rdi <- [vm.parent_fiber]
"mov rsp, [rdi + 16]", // rsp <- [parent.rsp_save]
"pop rbp",
"pop rbx",
"pop r12",
"pop r13",
"pop r14",
"pop r15",
"mov rax, rsi",
"ret",
options(noreturn)
);
}
}

Expand Down
4 changes: 2 additions & 2 deletions monoruby/src/executor/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,12 +447,12 @@ impl Globals {

fn fiber_tos(&self, val: Value) -> String {
let fiber = val.as_fiber();
let state = match unsafe { fiber.handle.as_ref().fiber_state() } {
let state = match fiber.state() {
FiberState::Created => "created",
FiberState::Terminated => "terminated",
FiberState::Suspended => "suspended",
};
let func_id = fiber.block_data.func_id();
let func_id = fiber.func_id();
format!(
"#<Fiber:0x{:016x} {} ({state})>",
val.get(),
Expand Down
5 changes: 5 additions & 0 deletions monoruby/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,11 @@ impl Value {
assert_eq!(ObjKind::FIBER, self.rvalue().kind());
self.rvalue().as_fiber()
}

pub fn as_fiber_mut(&mut self) -> &mut FiberInner {
assert_eq!(ObjKind::FIBER, self.rvalue().kind());
self.rvalue_mut().as_fiber_mut()
}
}

impl Value {
Expand Down
Loading

0 comments on commit b173522

Please sign in to comment.