Skip to content

Commit

Permalink
drop runtime borrows for system
Browse files Browse the repository at this point in the history
  • Loading branch information
dragazo committed Nov 13, 2023
1 parent e98d8e8 commit 9369dc9
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "netsblox-vm"
version = "0.2.18"
version = "0.2.19"
edition = "2021"
license = "MIT OR Apache-2.0"
authors = ["Devin Jean <[email protected]>"]
Expand Down
50 changes: 45 additions & 5 deletions src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,9 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
}
}

let mut global_context = self.global_context.borrow_mut(mc);
let global_context = &mut *global_context;
let mut global_context_raw = self.global_context.borrow_mut(mc);
let global_context = &mut *global_context_raw;

macro_rules! lookup_var {
($var:expr => $m:ident) => {{
let var = $var;
Expand Down Expand Up @@ -996,6 +997,7 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
let arg_count = arg_names.len();
let args = iter::zip(arg_names, self.value_stack.drain(self.value_stack.len() - arg_count..)).collect();

drop(global_context_raw);
self.defer = Some(Defer::Request {
key: system.perform_request(mc, Request::Rpc { service, rpc, args }, self)?,
action: RequestAction::Rpc,
Expand All @@ -1016,6 +1018,7 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
};
let name = self.value_stack.pop().unwrap().as_string()?.into_owned();

drop(global_context_raw);
self.defer = Some(Defer::Request {
key: system.perform_request(mc, Request::Syscall { name, args }, self)?,
action: RequestAction::Syscall,
Expand Down Expand Up @@ -1055,6 +1058,8 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
Instruction::Print { style } => {
let value = self.value_stack.pop().unwrap();
let is_empty = match &value { Value::String(x) => x.is_empty(), _ => false };

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::Print { style, value: if is_empty { None } else { Some(value) } }, self)?,
aft_pos,
Expand All @@ -1064,6 +1069,7 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
let prompt = self.value_stack.pop().unwrap();
let is_empty = match &prompt { Value::String(x) => x.is_empty(), _ => false };

drop(global_context_raw);
self.defer = Some(Defer::Request {
key: system.perform_request(mc, Request::Input { prompt: if is_empty { None } else { Some(prompt) } }, self)?,
action: RequestAction::Input,
Expand Down Expand Up @@ -1146,6 +1152,7 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
self.pos = aft_pos;
}
Instruction::PushProperty { prop } => {
drop(global_context_raw);
self.defer = Some(Defer::Request {
key: system.perform_request(mc, Request::Property { prop }, self)?,
action: RequestAction::Push,
Expand All @@ -1154,13 +1161,17 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
}
Instruction::SetProperty { prop } => {
let value = self.value_stack.pop().unwrap();

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::SetProperty { prop, value }, self)?,
aft_pos,
});
}
Instruction::ChangeProperty { prop } => {
let delta = self.value_stack.pop().unwrap();

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::ChangeProperty { prop, delta }, self)?,
aft_pos,
Expand All @@ -1183,7 +1194,9 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
self.pos = aft_pos;
}
Instruction::SetCostume => {
let mut entity = self.current_entity().borrow_mut(mc);
let mut entity_raw = self.current_entity().borrow_mut(mc);
let entity = &mut *entity_raw;

let new_costume = match self.value_stack.pop().unwrap() {
Value::Image(x) => Some(x),
Value::String(x) => match x.as_str() {
Expand All @@ -1198,6 +1211,9 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {

if new_costume.as_ref().map(Rc::as_ptr) != entity.costume.as_ref().map(Rc::as_ptr) {
entity.costume = new_costume;

drop(entity_raw);
drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::SetCostume, self)?,
aft_pos,
Expand All @@ -1207,13 +1223,18 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
}
}
Instruction::NextCostume => {
let mut entity = self.current_entity().borrow_mut(mc);
let mut entity_raw = self.current_entity().borrow_mut(mc);
let entity = &mut *entity_raw;

match entity.costume.as_ref().and_then(|x| entity.costume_list.iter().enumerate().find(|c| Rc::ptr_eq(x, &c.1.1))).map(|x| x.0) {
Some(idx) => {
let new_costume = Some(entity.costume_list[(idx + 1) % entity.costume_list.len()].1.clone());

if new_costume.as_ref().map(Rc::as_ptr) != entity.costume.as_ref().map(Rc::as_ptr) {
entity.costume = new_costume;

drop(entity_raw);
drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::SetCostume, self)?,
aft_pos,
Expand Down Expand Up @@ -1243,12 +1264,14 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
return Ok(ProcessStep::CreatedClone { new_entity });
}
Instruction::ClearEffects => {
drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::ClearEffects, self)?,
aft_pos,
});
}
Instruction::ClearDrawings => {
drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::ClearDrawings, self)?,
aft_pos,
Expand All @@ -1257,6 +1280,8 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
Instruction::GotoXY => {
let y = self.value_stack.pop().unwrap().as_number()?;
let x = self.value_stack.pop().unwrap().as_number()?;

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::GotoXY { x, y }, self)?,
aft_pos,
Expand All @@ -1267,13 +1292,17 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
let target = target.borrow();
if target.len() != 2 { return Err(ErrorCause::InvalidListLength { expected: 2, got: target.len() }); }
let (x, y) = (target[0].as_number()?, target[1].as_number()?);

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::GotoXY { x, y }, self)?,
aft_pos,
});
}
Value::Entity(target) => {
let target = target.borrow();

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::GotoEntity { target: &*target }, self)?,
aft_pos,
Expand All @@ -1284,6 +1313,8 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
Instruction::PointTowardsXY => {
let x = self.value_stack.pop().unwrap().as_number()?;
let y = self.value_stack.pop().unwrap().as_number()?;

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::PointTowardsXY { x, y }, self)?,
aft_pos,
Expand All @@ -1294,13 +1325,17 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
let target = target.borrow();
if target.len() != 2 { return Err(ErrorCause::InvalidListLength { expected: 2, got: target.len() }); }
let (x, y) = (target[0].as_number()?, target[1].as_number()?);

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::PointTowardsXY { x, y }, self)?,
aft_pos,
});
}
Value::Entity(target) => {
let target = target.borrow();

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::PointTowardsEntity { target: &*target }, self)?,
aft_pos,
Expand All @@ -1310,15 +1345,20 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
}
Instruction::Forward => {
let distance = self.value_stack.pop().unwrap().as_number()?;

drop(global_context_raw);
self.defer = Some(Defer::Command {
key: system.perform_command(mc, Command::Forward { distance }, self)?,
aft_pos,
});
}
Instruction::UnknownBlock { name, args } => {
let name = name.to_owned();
let args = self.value_stack.drain(self.value_stack.len() - args..).collect();

drop(global_context_raw);
self.defer = Some(Defer::Request {
key: system.perform_request(mc, Request::UnknownBlock { name: name.into(), args }, self)?,
key: system.perform_request(mc, Request::UnknownBlock { name, args }, self)?,
action: RequestAction::Push,
aft_pos
});
Expand Down
31 changes: 29 additions & 2 deletions src/std_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,21 @@ impl<C: CustomTypes<StdSystem<C>>> StdSystem<C> {
pub fn inject_message(&self, msg_type: String, values: Vec<(String, SimpleValue)>) {
self.message_injector.send(IncomingMessage { msg_type, values, reply_key: None }).unwrap();
}

#[cfg(debug_assertions)]
fn check_entity_borrowing<'gc>(mc: &Mutation<'gc>, entity: &mut Entity<'gc, C, Self>) {
if let Some(original) = entity.original {
Self::check_entity_borrowing(mc, &mut *original.borrow_mut(mc));
}
}
#[cfg(debug_assertions)]
fn check_proc_borrowing<'gc>(mc: &Mutation<'gc>, proc: &mut Process<'gc, C, Self>) {
Self::check_entity_borrowing(mc, &mut *proc.current_entity().borrow_mut(mc));
let global_context = proc.global_context.borrow_mut(mc);
for entity in global_context.entities.iter() {
Self::check_entity_borrowing(mc, &mut *entity.1.borrow_mut(mc));
}
}
}
impl<C: CustomTypes<StdSystem<C>>> System<C> for StdSystem<C> {
type RequestKey = RequestKey<C>;
Expand All @@ -419,6 +434,9 @@ impl<C: CustomTypes<StdSystem<C>>> System<C> for StdSystem<C> {
}

fn perform_request<'gc>(&self, mc: &Mutation<'gc>, request: Request<'gc, C, Self>, proc: &mut Process<'gc, C, Self>) -> Result<Self::RequestKey, ErrorCause<C, Self>> {
#[cfg(debug_assertions)]
Self::check_proc_borrowing(mc, proc);

Ok(match self.config.request.as_ref() {
Some(handler) => {
let key = RequestKey(Arc::new(Mutex::new(AsyncResult::new())));
Expand All @@ -430,7 +448,10 @@ impl<C: CustomTypes<StdSystem<C>>> System<C> for StdSystem<C> {
None => return Err(ErrorCause::NotSupported { feature: request.feature() }),
})
}
fn poll_request<'gc>(&self, mc: &Mutation<'gc>, key: &Self::RequestKey, _: &mut Process<'gc, C, Self>) -> Result<AsyncResult<Result<Value<'gc, C, Self>, String>>, ErrorCause<C, Self>> {
fn poll_request<'gc>(&self, mc: &Mutation<'gc>, key: &Self::RequestKey, proc: &mut Process<'gc, C, Self>) -> Result<AsyncResult<Result<Value<'gc, C, Self>, String>>, ErrorCause<C, Self>> {

Check warning on line 451 in src/std_system.rs

View workflow job for this annotation

GitHub Actions / test (--release)

unused variable: `proc`
#[cfg(debug_assertions)]
Self::check_proc_borrowing(mc, proc);

Ok(match key.poll() {
AsyncResult::Completed(Ok(x)) => AsyncResult::Completed(Ok(C::from_intermediate(mc, x)?)),
AsyncResult::Completed(Err(x)) => AsyncResult::Completed(Err(x)),
Expand All @@ -440,6 +461,9 @@ impl<C: CustomTypes<StdSystem<C>>> System<C> for StdSystem<C> {
}

fn perform_command<'gc>(&self, mc: &Mutation<'gc>, command: Command<'gc, '_, C, Self>, proc: &mut Process<'gc, C, Self>) -> Result<Self::CommandKey, ErrorCause<C, Self>> {
#[cfg(debug_assertions)]
Self::check_proc_borrowing(mc, proc);

Ok(match self.config.command.as_ref() {
Some(handler) => {
let key = CommandKey(Arc::new(Mutex::new(AsyncResult::new())));
Expand All @@ -451,7 +475,10 @@ impl<C: CustomTypes<StdSystem<C>>> System<C> for StdSystem<C> {
None => return Err(ErrorCause::NotSupported { feature: command.feature() }),
})
}
fn poll_command<'gc>(&self, _: &Mutation<'gc>, key: &Self::CommandKey, _: &mut Process<'gc, C, Self>) -> Result<AsyncResult<Result<(), String>>, ErrorCause<C, Self>> {
fn poll_command<'gc>(&self, mc: &Mutation<'gc>, key: &Self::CommandKey, proc: &mut Process<'gc, C, Self>) -> Result<AsyncResult<Result<(), String>>, ErrorCause<C, Self>> {

Check warning on line 478 in src/std_system.rs

View workflow job for this annotation

GitHub Actions / test (--release)

unused variable: `mc`

Check warning on line 478 in src/std_system.rs

View workflow job for this annotation

GitHub Actions / test (--release)

unused variable: `proc`
#[cfg(debug_assertions)]
Self::check_proc_borrowing(mc, proc);

Ok(key.poll())
}

Expand Down

0 comments on commit 9369dc9

Please sign in to comment.