Skip to content

Commit 653fff9

Browse files
committed
core: Replace GcCell with Gc in MorphShape
This refactor replaces GcCell with Gc and uses interior mutability instead.
1 parent 3fd5e50 commit 653fff9

File tree

2 files changed

+35
-33
lines changed

2 files changed

+35
-33
lines changed

core/src/display_object.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2237,7 +2237,7 @@ pub trait TDisplayObject<'gc>:
22372237
}
22382238
}
22392239
if let Some(ratio) = place_object.ratio {
2240-
if let Some(mut morph_shape) = self.as_morph_shape() {
2240+
if let Some(morph_shape) = self.as_morph_shape() {
22412241
morph_shape.set_ratio(context.gc(), ratio);
22422242
} else if let Some(video) = self.as_video() {
22432243
video.seek(context, ratio.into());

core/src/display_object/morph_shape.rs

+34-32
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,35 @@ use crate::library::{Library, MovieLibrarySource};
77
use crate::prelude::*;
88
use crate::tag_utils::SwfMovie;
99
use core::fmt;
10-
use gc_arena::{Collect, Gc, GcCell, Mutation};
10+
use gc_arena::barrier::unlock;
11+
use gc_arena::lock::{Lock, RefLock};
12+
use gc_arena::{Collect, Gc, Mutation};
1113
use ruffle_render::backend::ShapeHandle;
1214
use ruffle_render::commands::CommandHandler;
13-
use std::cell::{Ref, RefCell, RefMut};
15+
use std::cell::{Cell, Ref, RefCell, RefMut};
1416
use std::sync::Arc;
1517
use swf::{Fixed16, Fixed8};
1618

1719
#[derive(Clone, Collect, Copy)]
1820
#[collect(no_drop)]
19-
pub struct MorphShape<'gc>(GcCell<'gc, MorphShapeData<'gc>>);
21+
pub struct MorphShape<'gc>(Gc<'gc, MorphShapeData<'gc>>);
2022

2123
impl fmt::Debug for MorphShape<'_> {
2224
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2325
f.debug_struct("MorphShape")
24-
.field("ptr", &self.0.as_ptr())
26+
.field("ptr", &Gc::as_ptr(self.0))
2527
.finish()
2628
}
2729
}
2830

2931
#[derive(Clone, Collect)]
3032
#[collect(no_drop)]
3133
pub struct MorphShapeData<'gc> {
32-
base: DisplayObjectBase<'gc>,
33-
shared: Gc<'gc, MorphShapeShared>,
34-
ratio: u16,
34+
base: RefLock<DisplayObjectBase<'gc>>,
35+
shared: Lock<Gc<'gc, MorphShapeShared>>,
36+
ratio: Cell<u16>,
3537
/// The AVM2 representation of this MorphShape.
36-
object: Option<Avm2Object<'gc>>,
38+
object: Lock<Option<Avm2Object<'gc>>>,
3739
}
3840

3941
impl<'gc> MorphShape<'gc> {
@@ -43,46 +45,46 @@ impl<'gc> MorphShape<'gc> {
4345
movie: Arc<SwfMovie>,
4446
) -> Self {
4547
let shared = MorphShapeShared::from_swf_tag(&tag, movie);
46-
MorphShape(GcCell::new(
48+
MorphShape(Gc::new(
4749
gc_context,
4850
MorphShapeData {
4951
base: Default::default(),
50-
shared: Gc::new(gc_context, shared),
51-
ratio: 0,
52-
object: None,
52+
shared: Lock::new(Gc::new(gc_context, shared)),
53+
ratio: Cell::new(0),
54+
object: Lock::new(None),
5355
},
5456
))
5557
}
5658

5759
pub fn ratio(self) -> u16 {
58-
self.0.read().ratio
60+
self.0.ratio.get()
5961
}
6062

61-
pub fn set_ratio(&mut self, gc_context: &Mutation<'gc>, ratio: u16) {
62-
self.0.write(gc_context).ratio = ratio;
63+
pub fn set_ratio(self, gc_context: &Mutation<'gc>, ratio: u16) {
64+
self.0.ratio.set(ratio);
6365
self.invalidate_cached_bitmap(gc_context);
6466
}
6567
}
6668

6769
impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
6870
fn base(&self) -> Ref<DisplayObjectBase<'gc>> {
69-
Ref::map(self.0.read(), |r| &r.base)
71+
self.0.base.borrow()
7072
}
7173

7274
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
73-
RefMut::map(self.0.write(mc), |w| &mut w.base)
75+
unlock!(Gc::write(mc, self.0), MorphShapeData, base).borrow_mut()
7476
}
7577

7678
fn instantiate(&self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc> {
77-
Self(GcCell::new(gc_context, self.0.read().clone())).into()
79+
Self(Gc::new(gc_context, self.0.as_ref().clone())).into()
7880
}
7981

8082
fn as_ptr(&self) -> *const DisplayObjectPtr {
81-
self.0.as_ptr() as *const DisplayObjectPtr
83+
Gc::as_ptr(self.0) as *const DisplayObjectPtr
8284
}
8385

8486
fn id(&self) -> CharacterId {
85-
self.0.read().shared.id
87+
self.0.shared.get().id
8688
}
8789

8890
fn as_morph_shape(&self) -> Option<Self> {
@@ -95,7 +97,8 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
9597
.library_for_movie_mut(self.movie())
9698
.get_morph_shape(id)
9799
{
98-
self.0.write(context.gc()).shared = new_morph_shape.0.read().shared;
100+
unlock!(Gc::write(context.gc(), self.0), MorphShapeData, shared)
101+
.set(new_morph_shape.0.shared.get())
99102
} else {
100103
tracing::warn!("PlaceObject: expected morph shape at character ID {}", id);
101104
}
@@ -108,14 +111,15 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
108111

109112
fn object2(&self) -> Avm2Value<'gc> {
110113
self.0
111-
.read()
112114
.object
115+
.get()
113116
.map(Avm2Value::from)
114117
.unwrap_or(Avm2Value::Null)
115118
}
116119

117120
fn set_object2(&self, context: &mut UpdateContext<'gc>, to: Avm2Object<'gc>) {
118-
self.0.write(context.gc()).object = Some(to);
121+
let mc = context.gc();
122+
unlock!(Gc::write(mc, self.0), MorphShapeData, object).set(Some(to))
119123
}
120124

121125
/// Construct objects placed on this frame.
@@ -128,27 +132,25 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
128132
(*self).into(),
129133
class,
130134
) {
131-
Ok(object) => self.0.write(context.gc()).object = Some(object.into()),
135+
Ok(object) => self.set_object2(context, object.into()),
132136
Err(e) => tracing::error!("Got {} when constructing AVM2 side of MorphShape", e),
133137
};
134138
self.on_construction_complete(context);
135139
}
136140
}
137141

138142
fn render_self(&self, context: &mut RenderContext) {
139-
let this = self.0.read();
140-
let ratio = this.ratio;
141-
let shared = this.shared;
143+
let ratio = self.0.ratio.get();
144+
let shared = self.0.shared.get();
142145
let shape_handle = shared.get_shape(context, context.library, ratio);
143146
context
144147
.commands
145148
.render_shape(shape_handle, context.transform_stack.transform());
146149
}
147150

148151
fn self_bounds(&self) -> Rectangle<Twips> {
149-
let this = self.0.read();
150-
let ratio = this.ratio;
151-
let shared = this.shared;
152+
let ratio = self.0.ratio.get();
153+
let shared = self.0.shared.get();
152154
let frame = shared.get_frame(ratio);
153155
frame.bounds.clone()
154156
}
@@ -162,7 +164,7 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
162164
if (!options.contains(HitTestOptions::SKIP_INVISIBLE) || self.visible())
163165
&& self.world_bounds().contains(point)
164166
{
165-
if let Some(frame) = self.0.read().shared.frames.borrow().get(&self.ratio()) {
167+
if let Some(frame) = self.0.shared.get().frames.borrow().get(&self.ratio()) {
166168
let Some(local_matrix) = self.global_to_local_matrix() else {
167169
return false;
168170
};
@@ -180,7 +182,7 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
180182
}
181183

182184
fn movie(&self) -> Arc<SwfMovie> {
183-
self.0.read().shared.movie.clone()
185+
self.0.shared.get().movie.clone()
184186
}
185187
}
186188

0 commit comments

Comments
 (0)