diff --git a/core/src/avm2.rs b/core/src/avm2.rs index edb319885..a5a52426d 100644 --- a/core/src/avm2.rs +++ b/core/src/avm2.rs @@ -15,7 +15,8 @@ use crate::tag_utils::SwfMovie; use crate::PlayerRuntime; use fnv::FnvHashMap; -use gc_arena::{Collect, GcCell, Mutation}; +use gc_arena::lock::GcRefLock; +use gc_arena::{Collect, Mutation}; use std::sync::Arc; use swf::avm2::read::Reader; use swf::DoAbc2Flag; @@ -112,7 +113,7 @@ pub struct Avm2<'gc> { scope_stack: Vec>, /// The current call stack of the player. - call_stack: GcCell<'gc, CallStack<'gc>>, + call_stack: GcRefLock<'gc, CallStack<'gc>>, /// This domain is used exclusively for classes from playerglobals playerglobals_domain: Domain<'gc>, @@ -216,7 +217,7 @@ impl<'gc> Avm2<'gc> { player_runtime, stack: Vec::new(), scope_stack: Vec::new(), - call_stack: GcCell::new(context.gc_context, CallStack::new()), + call_stack: GcRefLock::new(context.gc_context, CallStack::new().into()), playerglobals_domain, stage_domain, system_classes: None, @@ -650,20 +651,20 @@ impl<'gc> Avm2<'gc> { method: Method<'gc>, superclass: Option>, ) { - self.call_stack.write(mc).push(method, superclass) + self.call_stack.borrow_mut(mc).push(method, superclass) } /// Pushes script initializer (global init) on the call stack pub fn push_global_init(&self, mc: &Mutation<'gc>, script: Script<'gc>) { - self.call_stack.write(mc).push_global_init(script) + self.call_stack.borrow_mut(mc).push_global_init(script) } /// Pops an executable off the call stack pub fn pop_call(&self, mc: &Mutation<'gc>) -> Option> { - self.call_stack.write(mc).pop() + self.call_stack.borrow_mut(mc).pop() } - pub fn call_stack(&self) -> GcCell<'gc, CallStack<'gc>> { + pub fn call_stack(&self) -> GcRefLock<'gc, CallStack<'gc>> { self.call_stack } diff --git a/core/src/avm2/object/error_object.rs b/core/src/avm2/object/error_object.rs index 9be8ed63f..15b00fd9e 100644 --- a/core/src/avm2/object/error_object.rs +++ b/core/src/avm2/object/error_object.rs @@ -20,7 +20,7 @@ pub fn error_allocator<'gc>( let base = ScriptObjectData::new(class); let call_stack = (enabled!(Level::INFO) || cfg!(feature = "avm_debug")) - .then(|| activation.avm2().call_stack().read().clone()) + .then(|| activation.avm2().call_stack().borrow().clone()) .unwrap_or_default(); Ok(ErrorObject(Gc::new( diff --git a/core/src/player.rs b/core/src/player.rs index 3df5d376f..ec8cef119 100644 --- a/core/src/player.rs +++ b/core/src/player.rs @@ -50,7 +50,8 @@ use crate::tag_utils::SwfMovie; use crate::timer::Timers; use crate::vminterface::Instantiator; use crate::DefaultFont; -use gc_arena::{Collect, DynamicRootSet, GcCell, Rootable}; +use gc_arena::lock::GcRefLock; +use gc_arena::{Collect, DynamicRootSet, Rootable}; use rand::{rngs::SmallRng, SeedableRng}; use ruffle_render::backend::{null::NullRenderer, RenderBackend, ViewportDimensions}; use ruffle_render::commands::CommandList; @@ -77,14 +78,8 @@ pub const FALLBACK_DEVICE_FONT_TAG: &[u8] = include_bytes!("../assets/noto-sans- #[derive(Collect)] #[collect(no_drop)] struct GcRoot<'gc> { - callstack: GcCell<'gc, GcCallstack<'gc>>, - data: GcCell<'gc, GcRootData<'gc>>, -} - -#[derive(Collect, Default)] -#[collect(no_drop)] -struct GcCallstack<'gc> { - avm2: Option>>, + avm2_callstack: GcRefLock<'gc, CallStack<'gc>>, + data: GcRefLock<'gc, GcRootData<'gc>>, } #[derive(Clone)] @@ -97,12 +92,9 @@ impl StaticCallstack { if let Some(arena) = self.arena.upgrade() { if let Ok(arena) = arena.try_borrow() { arena.mutate(|_, root| { - let callstack = root.callstack.read(); - if let Some(callstack) = callstack.avm2 { - let stack = callstack.read(); - if !stack.is_empty() { - f(&stack) - } + let callstack = root.avm2_callstack.borrow(); + if !callstack.is_empty() { + f(&callstack); } }) } @@ -635,7 +627,7 @@ impl Player { pub fn clear_custom_menu_items(&mut self) { self.gc_arena.borrow().mutate(|gc_context, gc_root| { - let mut root_data = gc_root.data.write(gc_context); + let mut root_data = gc_root.data.borrow_mut(gc_context); root_data.current_context_menu = None; }); } @@ -1924,7 +1916,7 @@ impl Player { let invalidated = self .gc_arena .borrow() - .mutate(|_, gc_root| gc_root.data.read().stage.invalidated()); + .mutate(|_, gc_root| gc_root.data.borrow().stage.invalidated()); if invalidated { self.update(|context| { let stage = context.stage; @@ -1935,7 +1927,7 @@ impl Player { let mut background_color = Color::WHITE; let (cache_draws, commands) = self.gc_arena.borrow().mutate(|gc_context, gc_root| { - let root_data = gc_root.data.read(); + let root_data = gc_root.data.borrow(); let stage = root_data.stage; let mut cache_draws = vec![]; @@ -2135,7 +2127,7 @@ impl Player { F: for<'a, 'gc> FnOnce(&mut UpdateContext<'a, 'gc>) -> R, { self.gc_arena.borrow().mutate(|gc_context, gc_root| { - let mut root_data = gc_root.data.write(gc_context); + let mut root_data = gc_root.data.borrow_mut(gc_context); #[allow(unused_variables)] let ( @@ -2726,45 +2718,43 @@ impl PlayerBuilder { gc_context, interner: &mut interner, }; - let dynamic_root = DynamicRootSet::new(gc_context); + + let data = GcRootData { + audio_manager: AudioManager::new(), + action_queue: ActionQueue::new(), + avm1: Avm1::new(&mut init, player_version), + avm2: Avm2::new(&mut init, player_version, player_runtime), + interner, + current_context_menu: None, + drag_object: None, + external_interface: ExternalInterface::new( + external_interface_providers, + fs_command_provider, + ), + library: Library::empty(), + load_manager: LoadManager::new(), + mouse_data: MouseData { + hovered: None, + pressed: None, + right_pressed: None, + middle_pressed: None, + }, + avm1_shared_objects: HashMap::new(), + avm2_shared_objects: HashMap::new(), + stage: Stage::empty(gc_context, fullscreen, fake_movie), + timers: Timers::new(), + unbound_text_fields: Vec::new(), + stream_manager: StreamManager::new(), + sockets: Sockets::empty(), + net_connections: NetConnections::default(), + local_connections: LocalConnections::empty(), + dynamic_root: DynamicRootSet::new(gc_context), + post_frame_callbacks: Vec::new(), + }; GcRoot { - callstack: GcCell::new(gc_context, GcCallstack::default()), - data: GcCell::new( - gc_context, - GcRootData { - audio_manager: AudioManager::new(), - action_queue: ActionQueue::new(), - avm1: Avm1::new(&mut init, player_version), - avm2: Avm2::new(&mut init, player_version, player_runtime), - interner, - current_context_menu: None, - drag_object: None, - external_interface: ExternalInterface::new( - external_interface_providers, - fs_command_provider, - ), - library: Library::empty(), - load_manager: LoadManager::new(), - mouse_data: MouseData { - hovered: None, - pressed: None, - right_pressed: None, - middle_pressed: None, - }, - avm1_shared_objects: HashMap::new(), - avm2_shared_objects: HashMap::new(), - stage: Stage::empty(gc_context, fullscreen, fake_movie), - timers: Timers::new(), - unbound_text_fields: Vec::new(), - stream_manager: StreamManager::new(), - sockets: Sockets::empty(), - net_connections: NetConnections::default(), - local_connections: LocalConnections::empty(), - dynamic_root, - post_frame_callbacks: Vec::new(), - }, - ), + avm2_callstack: data.avm2.call_stack(), + data: GcRefLock::new(gc_context, data.into()), } } @@ -2915,10 +2905,6 @@ impl PlayerBuilder { crate::avm2::specification::capture_specification(context, &stub_path); } }); - player_lock.gc_arena.borrow().mutate(|context, root| { - let call_stack = root.data.read().avm2.call_stack(); - root.callstack.write(context).avm2 = Some(call_stack); - }); player_lock.audio.set_frame_rate(frame_rate); player_lock.set_letterbox(self.letterbox); player_lock.set_quality(self.quality);