Skip to content

Commit 8642905

Browse files
committed
core: Coalesce RefLocks in MovieClipData
Except `queued_tags`, which is kept separate to not require write barriers.
1 parent a9b9b46 commit 8642905

File tree

1 file changed

+49
-45
lines changed

1 file changed

+49
-45
lines changed

core/src/display_object/movie_clip.rs

Lines changed: 49 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -149,19 +149,17 @@ impl<'gc> MovieClipWeak<'gc> {
149149
#[derive(Clone, Collect)]
150150
#[collect(no_drop)]
151151
pub struct MovieClipData<'gc> {
152-
base: RefLock<InteractiveObjectBase<'gc>>,
152+
cell: RefLock<MovieClipDataMut<'gc>>,
153153
shared: Lock<Gc<'gc, MovieClipShared<'gc>>>,
154154
tag_stream_pos: Cell<u64>,
155155
current_frame: Cell<FrameNumber>,
156156
#[collect(require_static)]
157157
audio_stream: Cell<Option<SoundInstanceHandle>>,
158-
container: RefLock<ChildContainer<'gc>>,
159158
object: Lock<Option<AvmObject<'gc>>>,
160159
#[collect(require_static)]
161160
clip_event_handlers: OnceCell<Box<[ClipEventHandler]>>,
162161
#[collect(require_static)]
163162
clip_event_flags: Cell<ClipEventFlag>,
164-
frame_scripts: RefLock<Vec<Option<Avm2Object<'gc>>>>,
165163
flags: Cell<MovieClipFlags>,
166164
/// This is lazily allocated on demand, to make `MovieClipData` smaller in the common case.
167165
#[collect(require_static)]
@@ -184,32 +182,41 @@ pub struct MovieClipData<'gc> {
184182
drop_target: Lock<Option<DisplayObject<'gc>>>,
185183

186184
/// List of tags queued up for the current frame.
187-
#[collect(require_static)]
188185
queued_tags: RefCell<HashMap<Depth, QueuedTagList>>,
189186

190187
/// Attached audio (AVM1)
191188
attached_audio: Lock<Option<NetStream<'gc>>>,
192189

193190
// If this movie was loaded from ImportAssets(2), this will be the parent movie.
194191
importer_movie: Option<Arc<SwfMovie>>,
192+
}
195193

196-
avm1_text_field_bindings: RefLock<Vec<Avm1TextFieldBinding<'gc>>>,
194+
#[derive(Clone, Collect)]
195+
#[collect(no_drop)]
196+
struct MovieClipDataMut<'gc> {
197+
base: InteractiveObjectBase<'gc>,
198+
container: ChildContainer<'gc>,
199+
frame_scripts: Vec<Option<Avm2Object<'gc>>>,
200+
avm1_text_field_bindings: Vec<Avm1TextFieldBinding<'gc>>,
197201
}
198202

199203
impl<'gc> MovieClipData<'gc> {
200204
fn new(shared: MovieClipShared<'gc>, mc: &Mutation<'gc>) -> Self {
201205
let movie = shared.movie();
202206
Self {
203-
base: Default::default(),
207+
cell: RefLock::new(MovieClipDataMut {
208+
base: Default::default(),
209+
container: ChildContainer::new(&movie),
210+
frame_scripts: Vec::new(),
211+
avm1_text_field_bindings: Vec::new(),
212+
}),
204213
shared: Lock::new(Gc::new(mc, shared)),
205214
tag_stream_pos: Cell::new(0),
206215
current_frame: Cell::new(0),
207216
audio_stream: Cell::new(None),
208-
container: RefLock::new(ChildContainer::new(&movie)),
209217
object: Lock::new(None),
210218
clip_event_handlers: OnceCell::new(),
211219
clip_event_flags: Cell::new(ClipEventFlag::empty()),
212-
frame_scripts: RefLock::new(Vec::new()),
213220
flags: Cell::new(MovieClipFlags::empty()),
214221
drawing: OnceCell::new(),
215222
avm2_enabled: Cell::new(true),
@@ -220,11 +227,10 @@ impl<'gc> MovieClipData<'gc> {
220227
has_pending_script: Cell::new(false),
221228
queued_goto_frame: Cell::new(None),
222229
drop_target: Lock::new(None),
223-
hit_area: Lock::new(None),
224230
queued_tags: Default::default(),
231+
hit_area: Lock::new(None),
225232
attached_audio: Lock::new(None),
226233
importer_movie: None,
227-
avm1_text_field_bindings: Default::default(),
228234
}
229235
}
230236

@@ -311,9 +317,9 @@ impl<'gc> MovieClip<'gc> {
311317
movie.num_frames(),
312318
loader_info.map(|l| l.0),
313319
);
314-
let data = MovieClipData::new(shared, activation.gc());
320+
let mut data = MovieClipData::new(shared, activation.gc());
315321
data.flags.set(MovieClipFlags::PLAYING);
316-
data.base.borrow().base.set_is_root(true);
322+
data.cell.get_mut().base.base.set_is_root(true);
317323

318324
let mc = MovieClip(Gc::new(activation.gc(), data));
319325
if let Some((_, loader_info)) = loader_info {
@@ -348,11 +354,11 @@ impl<'gc> MovieClip<'gc> {
348354
);
349355

350356
{
351-
let base = write.base.borrow();
352-
base.base.reset_for_movie_load();
353-
base.base.set_is_root(is_root);
357+
let mut write = unlock!(write, MovieClipData, cell).borrow_mut();
358+
write.base.base.reset_for_movie_load();
359+
write.base.base.set_is_root(is_root);
360+
write.container = ChildContainer::new(&movie);
354361
}
355-
unlock!(write, MovieClipData, container).replace(ChildContainer::new(&movie));
356362
unlock!(write, MovieClipData, shared).set(Gc::new(
357363
context.gc(),
358364
MovieClipShared::with_data(
@@ -885,12 +891,16 @@ impl<'gc> MovieClip<'gc> {
885891
}
886892

887893
pub fn has_frame_script(self, frame: FrameNumber) -> bool {
894+
self.frame_script(frame).is_some()
895+
}
896+
897+
fn frame_script(self, frame: FrameNumber) -> Option<Avm2Object<'gc>> {
888898
self.0
889-
.frame_scripts
899+
.cell
890900
.borrow()
901+
.frame_scripts
891902
.get(frame as usize)
892-
.map(|v| v.is_some())
893-
.unwrap_or_default()
903+
.and_then(|&v| v)
894904
}
895905

896906
/// This sets the current preload frame of this MovieClipto a given number (resulting
@@ -1425,7 +1435,7 @@ impl<'gc> MovieClip<'gc> {
14251435
// tags. The rest of the goto machinery can handle the side effects of
14261436
// a half-executed loop.
14271437
if self.0.loop_queued() {
1428-
self.0.queued_tags.take();
1438+
self.0.queued_tags.borrow_mut().clear();
14291439
}
14301440

14311441
if is_implicit {
@@ -1823,7 +1833,10 @@ impl<'gc> MovieClip<'gc> {
18231833
) {
18241834
let write = Gc::write(context.gc(), self.0);
18251835
let current_frame = write.current_frame();
1826-
let mut frame_scripts = unlock!(write, MovieClipData, frame_scripts).borrow_mut();
1836+
let mut frame_scripts =
1837+
RefMut::map(unlock!(write, MovieClipData, cell).borrow_mut(), |r| {
1838+
&mut r.frame_scripts
1839+
});
18271840

18281841
let index = frame_id as usize;
18291842
if let Some(callable) = callable {
@@ -2143,13 +2156,7 @@ impl<'gc> MovieClip<'gc> {
21432156
let is_fresh_frame = self.0.last_queued_script_frame.get() != Some(frame_id);
21442157

21452158
if is_fresh_frame {
2146-
if let Some(Some(callable)) = self
2147-
.0
2148-
.frame_scripts
2149-
.borrow()
2150-
.get(frame_id as usize)
2151-
.cloned()
2152-
{
2159+
if let Some(callable) = self.frame_script(frame_id) {
21532160
self.0.last_queued_script_frame.set(Some(frame_id));
21542161
self.0.has_pending_script.set(false);
21552162
self.0
@@ -2192,12 +2199,12 @@ impl<'gc> MovieClip<'gc> {
21922199

21932200
impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
21942201
fn base(&self) -> Ref<'_, DisplayObjectBase<'gc>> {
2195-
Ref::map(self.0.base.borrow(), |r| &r.base)
2202+
Ref::map(self.0.cell.borrow(), |r| &r.base.base)
21962203
}
21972204

21982205
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
2199-
let base = unlock!(Gc::write(mc, self.0), MovieClipData, base);
2200-
RefMut::map(base.borrow_mut(), |r| &mut r.base)
2206+
let write = unlock!(Gc::write(mc, self.0), MovieClipData, cell);
2207+
RefMut::map(write.borrow_mut(), |r| &mut r.base.base)
22012208
}
22022209

22032210
fn instantiate(self, mc: &Mutation<'gc>) -> DisplayObject<'gc> {
@@ -2312,12 +2319,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
23122319

23132320
// Check for frame-scripts before starting the frame-script phase,
23142321
// to differentiate the pre-existing scripts from those introduced during frame-script phase.
2315-
let has_pending_script = self
2316-
.0
2317-
.frame_scripts
2318-
.borrow()
2319-
.get(self.0.current_frame.get() as usize)
2320-
.is_some();
2322+
let has_pending_script = self.has_frame_script(self.0.current_frame.get());
23212323
self.0.has_pending_script.set(has_pending_script);
23222324
}
23232325

@@ -2554,8 +2556,8 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
25542556
fn avm1_text_field_bindings(&self) -> Option<Ref<'_, [Avm1TextFieldBinding<'gc>]>> {
25552557
let obj = self.0.object.get().and_then(|o| o.as_avm1_object());
25562558
obj.map(|_| {
2557-
let bindings = self.0.avm1_text_field_bindings.borrow();
2558-
Ref::map(bindings, |b| &**b)
2559+
let read = self.0.cell.borrow();
2560+
Ref::map(read, |r| r.avm1_text_field_bindings.as_slice())
25592561
})
25602562
}
25612563

@@ -2565,8 +2567,8 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
25652567
) -> Option<RefMut<'_, Vec<Avm1TextFieldBinding<'gc>>>> {
25662568
let obj = self.0.object.get().and_then(|o| o.as_avm1_object());
25672569
obj.map(|_| {
2568-
let write = Gc::write(mc, self.0);
2569-
unlock!(write, MovieClipData, avm1_text_field_bindings).borrow_mut()
2570+
let write = unlock!(Gc::write(mc, self.0), MovieClipData, cell);
2571+
RefMut::map(write.borrow_mut(), |r| &mut r.avm1_text_field_bindings)
25702572
})
25712573
}
25722574

@@ -2581,11 +2583,12 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
25812583

25822584
impl<'gc> TDisplayObjectContainer<'gc> for MovieClip<'gc> {
25832585
fn raw_container(&self) -> Ref<'_, ChildContainer<'gc>> {
2584-
self.0.container.borrow()
2586+
Ref::map(self.0.cell.borrow(), |r| &r.container)
25852587
}
25862588

25872589
fn raw_container_mut(&self, mc: &Mutation<'gc>) -> RefMut<'_, ChildContainer<'gc>> {
2588-
unlock!(Gc::write(mc, self.0), MovieClipData, container).borrow_mut()
2590+
let write = unlock!(Gc::write(mc, self.0), MovieClipData, cell);
2591+
RefMut::map(write.borrow_mut(), |r| &mut r.container)
25892592
}
25902593

25912594
fn is_tab_children_avm1(self, context: &mut UpdateContext<'gc>) -> bool {
@@ -2595,11 +2598,12 @@ impl<'gc> TDisplayObjectContainer<'gc> for MovieClip<'gc> {
25952598

25962599
impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> {
25972600
fn raw_interactive(&self) -> Ref<'_, InteractiveObjectBase<'gc>> {
2598-
self.0.base.borrow()
2601+
Ref::map(self.0.cell.borrow(), |r| &r.base)
25992602
}
26002603

26012604
fn raw_interactive_mut(&self, mc: &Mutation<'gc>) -> RefMut<'_, InteractiveObjectBase<'gc>> {
2602-
unlock!(Gc::write(mc, self.0), MovieClipData, base).borrow_mut()
2605+
let write = unlock!(Gc::write(mc, self.0), MovieClipData, cell);
2606+
RefMut::map(write.borrow_mut(), |r| &mut r.base)
26032607
}
26042608

26052609
fn as_displayobject(self) -> DisplayObject<'gc> {

0 commit comments

Comments
 (0)