Skip to content

Commit fb28ae7

Browse files
committed
core: Use HasPrefixField for DisplayObjectBase casts
...and add a new `TDisplayObjectObject::gc_base` method that can be used to provide `base(_mut)` default impls. Because DO structs are now `repr(C)`, also reorder fields in rough order of decreasing alignment to avoid adding extra padding.
1 parent 5ab3923 commit fb28ae7

File tree

13 files changed

+104
-136
lines changed

13 files changed

+104
-136
lines changed

core/src/display_object.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use crate::tag_utils::SwfMovie;
1414
use crate::types::{Degrees, Percent};
1515
use crate::vminterface::Instantiator;
1616
use bitflags::bitflags;
17-
use gc_arena::{Collect, Mutation};
17+
use gc_arena::lock::RefLock;
18+
use gc_arena::{Collect, Gc, Mutation};
1819
use ruffle_macros::{enum_trait_object, istr};
1920
use ruffle_render::perspective_projection::PerspectiveProjection;
2021
use ruffle_render::pixel_bender::PixelBenderShaderHandle;
@@ -1111,8 +1112,19 @@ pub fn apply_standard_mask_and_scroll<'gc, F>(
11111112
pub trait TDisplayObject<'gc>:
11121113
'gc + Clone + Copy + Collect<'gc> + Debug + Into<DisplayObject<'gc>>
11131114
{
1114-
fn base<'a>(&'a self) -> Ref<'a, DisplayObjectBase<'gc>>;
1115-
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>>;
1115+
fn gc_base(self) -> Gc<'gc, RefLock<DisplayObjectBase<'gc>>>;
1116+
1117+
#[no_dynamic]
1118+
#[inline(always)]
1119+
fn base<'a>(&'a self) -> Ref<'a, DisplayObjectBase<'gc>> {
1120+
self.gc_base().borrow()
1121+
}
1122+
1123+
#[no_dynamic]
1124+
#[inline(always)]
1125+
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
1126+
self.gc_base().borrow_mut(mc)
1127+
}
11161128

11171129
/// The `SCALE_ROTATION_CACHED` flag should only be set in SWFv5+.
11181130
/// So scaling/rotation values always have to get recalculated from the matrix in SWFv4.

core/src/display_object/avm1_button.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::tag_utils::{SwfMovie, SwfSlice};
1616
use crate::utils::HasPrefixField;
1717
use crate::vminterface::Instantiator;
1818
use core::fmt;
19-
use gc_arena::barrier::{field, unlock};
19+
use gc_arena::barrier::unlock;
2020
use gc_arena::lock::{Lock, RefLock};
2121
use gc_arena::{Collect, Gc, Mutation};
2222
use ruffle_macros::istr;
@@ -247,13 +247,8 @@ impl<'gc> Avm1Button<'gc> {
247247
}
248248

249249
impl<'gc> TDisplayObject<'gc> for Avm1Button<'gc> {
250-
fn base(&self) -> Ref<'_, DisplayObjectBase<'gc>> {
251-
self.0.base.base()
252-
}
253-
254-
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
255-
let base = field!(Gc::write(mc, self.0), Avm1ButtonData, base);
256-
InteractiveObjectBase::base_mut(base)
250+
fn gc_base(self) -> Gc<'gc, RefLock<DisplayObjectBase<'gc>>> {
251+
HasPrefixField::as_prefix_gc(self.raw_interactive())
257252
}
258253

259254
fn instantiate(self, mc: &Mutation<'gc>) -> DisplayObject<'gc> {
@@ -447,11 +442,7 @@ impl<'gc> TInteractiveObject<'gc> for Avm1Button<'gc> {
447442

448443
// The `keyPress` event doesn't fire if the button is inside another button.
449444
if matches!(event, ClipEvent::KeyPress { .. })
450-
&& self
451-
.base()
452-
.parent
453-
.and_then(|p| p.as_avm1_button())
454-
.is_some()
445+
&& self.parent().and_then(|p| p.as_avm1_button()).is_some()
455446
{
456447
return ClipEventResult::NotHandled;
457448
}
@@ -623,7 +614,7 @@ impl<'gc> Avm1ButtonData<'gc> {
623614
condition: ButtonActionCondition,
624615
) -> ClipEventResult {
625616
let mut handled = ClipEventResult::NotHandled;
626-
if let Some(parent) = self.base.base().parent {
617+
if let Some(parent) = self.base.base.borrow().parent {
627618
for action in &self.shared.actions {
628619
if action.conditions.matches(condition) {
629620
// Note that AVM1 buttons run actions relative to their parent, not themselves.

core/src/display_object/avm2_button.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ use crate::tag_utils::{SwfMovie, SwfSlice};
2222
use crate::utils::HasPrefixField;
2323
use crate::vminterface::Instantiator;
2424
use core::fmt;
25-
use gc_arena::barrier::{field, unlock};
26-
use gc_arena::lock::Lock;
25+
use gc_arena::barrier::unlock;
26+
use gc_arena::lock::{Lock, RefLock};
2727
use gc_arena::{Collect, Gc, Mutation};
2828
use ruffle_render::filters::Filter;
29-
use std::cell::{Cell, Ref, RefCell, RefMut};
29+
use std::cell::{Cell, RefCell};
3030
use std::sync::Arc;
3131

3232
#[derive(Clone, Collect, Copy)]
@@ -413,13 +413,8 @@ impl<'gc> Avm2Button<'gc> {
413413
}
414414

415415
impl<'gc> TDisplayObject<'gc> for Avm2Button<'gc> {
416-
fn base(&self) -> Ref<'_, DisplayObjectBase<'gc>> {
417-
self.0.base.base()
418-
}
419-
420-
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
421-
let base = field!(Gc::write(mc, self.0), Avm2ButtonData, base);
422-
InteractiveObjectBase::base_mut(base)
416+
fn gc_base(self) -> Gc<'gc, RefLock<DisplayObjectBase<'gc>>> {
417+
HasPrefixField::as_prefix_gc(self.raw_interactive())
423418
}
424419

425420
fn instantiate(self, mc: &Mutation<'gc>) -> DisplayObject<'gc> {

core/src/display_object/bitmap.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ use crate::context::{RenderContext, UpdateContext};
1111
use crate::display_object::{DisplayObjectBase, DisplayObjectPtr, DisplayObjectWeak};
1212
use crate::prelude::*;
1313
use crate::tag_utils::SwfMovie;
14+
use crate::utils::HasPrefixField;
1415
use crate::vminterface::Instantiator;
1516
use core::fmt;
1617
use gc_arena::barrier::unlock;
1718
use gc_arena::lock::{Lock, RefLock};
1819
use gc_arena::{Collect, Gc, GcCell, GcWeak, Mutation};
1920
use ruffle_render::backend::RenderBackend;
2021
use ruffle_render::bitmap::{BitmapFormat, PixelSnapping};
21-
use std::cell::{Cell, Ref, RefMut};
22+
use std::cell::Cell;
2223
use std::sync::Arc;
2324

2425
#[derive(Clone, Debug, Collect, Copy)]
@@ -96,13 +97,22 @@ impl fmt::Debug for Bitmap<'_> {
9697
}
9798
}
9899

99-
#[derive(Clone, Collect)]
100+
#[derive(Clone, Collect, HasPrefixField)]
100101
#[collect(no_drop)]
102+
#[repr(C, align(8))]
101103
pub struct BitmapGraphicData<'gc> {
102104
base: RefLock<DisplayObjectBase<'gc>>,
103-
id: CharacterId,
104105
movie: Arc<SwfMovie>,
105106

107+
/// The AVM2 side of this object.
108+
///
109+
/// AVM1 code cannot directly reference `Bitmap`s, so this does not support
110+
/// storing an AVM1 object.
111+
avm2_object: Lock<Option<Avm2Object<'gc>>>,
112+
113+
/// The class associated with this Bitmap.
114+
avm2_bitmap_class: Lock<BitmapClass<'gc>>,
115+
106116
/// The current bitmap data object.
107117
bitmap_data: Lock<BitmapDataWrapper<'gc>>,
108118

@@ -112,20 +122,13 @@ pub struct BitmapGraphicData<'gc> {
112122
width: Cell<u32>,
113123
height: Cell<u32>,
114124

125+
id: CharacterId,
126+
115127
/// Whether or not bitmap smoothing is enabled.
116128
smoothing: Cell<bool>,
117129

118130
/// How to snap this bitmap to the pixel grid
119131
pixel_snapping: Cell<PixelSnapping>,
120-
121-
/// The AVM2 side of this object.
122-
///
123-
/// AVM1 code cannot directly reference `Bitmap`s, so this does not support
124-
/// storing an AVM1 object.
125-
avm2_object: Lock<Option<Avm2Object<'gc>>>,
126-
127-
/// The class associated with this Bitmap.
128-
avm2_bitmap_class: Lock<BitmapClass<'gc>>,
129132
}
130133

131134
impl<'gc> Bitmap<'gc> {
@@ -301,12 +304,8 @@ impl<'gc> Bitmap<'gc> {
301304
}
302305

303306
impl<'gc> TDisplayObject<'gc> for Bitmap<'gc> {
304-
fn base(&self) -> Ref<'_, DisplayObjectBase<'gc>> {
305-
self.0.base.borrow()
306-
}
307-
308-
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
309-
unlock!(Gc::write(mc, self.0), BitmapGraphicData, base).borrow_mut()
307+
fn gc_base(self) -> Gc<'gc, RefLock<DisplayObjectBase<'gc>>> {
308+
HasPrefixField::as_prefix_gc(self.0)
310309
}
311310

312311
fn instantiate(self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc> {

core/src/display_object/edit_text.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ use crate::vminterface::{AvmObject, Instantiator};
3333
use chrono::DateTime;
3434
use chrono::Utc;
3535
use core::fmt;
36-
use gc_arena::barrier::{field, unlock};
37-
use gc_arena::{Collect, Gc, Lock, Mutation, RefLock};
36+
use gc_arena::barrier::unlock;
37+
use gc_arena::lock::{Lock, RefLock};
38+
use gc_arena::{Collect, Gc, Mutation};
3839
use ruffle_macros::istr;
3940
use ruffle_render::commands::Command as RenderCommand;
4041
use ruffle_render::commands::CommandHandler;
@@ -2501,13 +2502,8 @@ impl<'gc> EditText<'gc> {
25012502
}
25022503

25032504
impl<'gc> TDisplayObject<'gc> for EditText<'gc> {
2504-
fn base(&self) -> Ref<'_, DisplayObjectBase<'gc>> {
2505-
self.0.base.base()
2506-
}
2507-
2508-
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
2509-
let base = field!(Gc::write(mc, self.0), EditTextData, base);
2510-
InteractiveObjectBase::base_mut(base)
2505+
fn gc_base(self) -> Gc<'gc, RefLock<DisplayObjectBase<'gc>>> {
2506+
HasPrefixField::as_prefix_gc(self.raw_interactive())
25112507
}
25122508

25132509
fn instantiate(self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc> {

core/src/display_object/graphic.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ use crate::drawing::Drawing;
99
use crate::library::MovieLibrarySource;
1010
use crate::prelude::*;
1111
use crate::tag_utils::SwfMovie;
12+
use crate::utils::HasPrefixField;
1213
use crate::vminterface::Instantiator;
1314
use core::fmt;
1415
use gc_arena::barrier::unlock;
15-
use gc_arena::{Collect, Gc, Lock, Mutation, RefLock};
16+
use gc_arena::lock::{Lock, RefLock};
17+
use gc_arena::{Collect, Gc, Mutation};
1618
use ruffle_render::backend::ShapeHandle;
1719
use ruffle_render::commands::CommandHandler;
18-
use std::cell::{OnceCell, Ref, RefCell, RefMut};
20+
use std::cell::{OnceCell, RefCell, RefMut};
1921
use std::sync::Arc;
2022

2123
#[derive(Clone, Collect, Copy)]
@@ -30,8 +32,9 @@ impl fmt::Debug for Graphic<'_> {
3032
}
3133
}
3234

33-
#[derive(Clone, Collect)]
35+
#[derive(Clone, Collect, HasPrefixField)]
3436
#[collect(no_drop)]
37+
#[repr(C, align(8))]
3538
pub struct GraphicData<'gc> {
3639
base: RefLock<DisplayObjectBase<'gc>>,
3740
shared: Lock<Gc<'gc, GraphicShared>>,
@@ -65,7 +68,7 @@ impl<'gc> Graphic<'gc> {
6568
Graphic(Gc::new(
6669
context.gc(),
6770
GraphicData {
68-
base: RefLock::new(Default::default()),
71+
base: Default::default(),
6972
shared: Lock::new(Gc::new(context.gc(), shared)),
7073
class: Lock::new(None),
7174
avm2_object: Lock::new(None),
@@ -121,12 +124,8 @@ impl<'gc> Graphic<'gc> {
121124
}
122125

123126
impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
124-
fn base(&self) -> Ref<'_, DisplayObjectBase<'gc>> {
125-
self.0.base.borrow()
126-
}
127-
128-
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
129-
unlock!(Gc::write(mc, self.0), GraphicData, base).borrow_mut()
127+
fn gc_base(self) -> Gc<'gc, RefLock<DisplayObjectBase<'gc>>> {
128+
HasPrefixField::as_prefix_gc(self.0)
130129
}
131130

132131
fn instantiate(self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc> {

core/src/display_object/interactive.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ use crate::display_object::{
1818
};
1919
use crate::events::{ClipEvent, ClipEventResult, MouseButton};
2020
use crate::string::AvmString;
21+
use crate::utils::HasPrefixField;
2122
use bitflags::bitflags;
22-
use gc_arena::barrier::{unlock, Write};
23+
use gc_arena::barrier::unlock;
2324
use gc_arena::lock::{Lock, RefLock};
2425
use gc_arena::{Collect, Gc, Mutation};
2526
use ruffle_macros::{enum_trait_object, istr};
26-
use std::cell::{Cell, Ref, RefMut};
27+
use std::cell::Cell;
2728
use std::fmt::Debug;
2829
use swf::{Point, Rectangle, Twips};
2930

@@ -81,19 +82,22 @@ bitflags! {
8182
}
8283
}
8384

84-
#[derive(Collect, Clone)]
85+
#[derive(Collect, Clone, HasPrefixField)]
8586
#[collect(no_drop)]
87+
#[repr(C, align(8))]
8688
pub struct InteractiveObjectBase<'gc> {
8789
pub base: RefLock<DisplayObjectBase<'gc>>,
88-
#[collect(require_static)]
89-
flags: Cell<InteractiveObjectFlags>,
90+
9091
context_menu: Lock<Avm2Value<'gc>>,
9192

9293
#[collect(require_static)]
93-
tab_enabled: Cell<Option<bool>>,
94+
tab_index: Cell<Option<i32>>,
9495

9596
#[collect(require_static)]
96-
tab_index: Cell<Option<i32>>,
97+
flags: Cell<InteractiveObjectFlags>,
98+
99+
#[collect(require_static)]
100+
tab_enabled: Cell<Option<bool>>,
97101

98102
/// Specifies whether this object displays a yellow rectangle when focused.
99103
focus_rect: Cell<Option<bool>>,
@@ -113,14 +117,6 @@ impl Default for InteractiveObjectBase<'_> {
113117
}
114118

115119
impl<'gc> InteractiveObjectBase<'gc> {
116-
pub fn base(&self) -> Ref<'_, DisplayObjectBase<'gc>> {
117-
self.base.borrow()
118-
}
119-
120-
pub fn base_mut(this: &Write<Self>) -> RefMut<'_, DisplayObjectBase<'gc>> {
121-
unlock!(this, Self, base).borrow_mut()
122-
}
123-
124120
fn contains_flag(&self, flag: InteractiveObjectFlags) -> bool {
125121
self.flags.get().contains(flag)
126122
}

core/src/display_object/loader_display.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::display_object::interactive::InteractiveObjectBase;
1313
use crate::tag_utils::SwfMovie;
1414
use crate::utils::HasPrefixField;
1515
use core::fmt;
16-
use gc_arena::barrier::{field, unlock};
16+
use gc_arena::barrier::unlock;
1717
use gc_arena::lock::{Lock, RefLock};
1818
use gc_arena::{Collect, Gc, GcWeak, Mutation};
1919
use std::cell::{Ref, RefMut};
@@ -66,13 +66,8 @@ impl<'gc> LoaderDisplay<'gc> {
6666
}
6767

6868
impl<'gc> TDisplayObject<'gc> for LoaderDisplay<'gc> {
69-
fn base(&self) -> Ref<'_, DisplayObjectBase<'gc>> {
70-
self.0.base.base()
71-
}
72-
73-
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
74-
let base = field!(Gc::write(mc, self.0), LoaderDisplayData, base);
75-
InteractiveObjectBase::base_mut(base)
69+
fn gc_base(self) -> Gc<'gc, RefLock<DisplayObjectBase<'gc>>> {
70+
HasPrefixField::as_prefix_gc(self.raw_interactive())
7671
}
7772

7873
fn instantiate(self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc> {

0 commit comments

Comments
 (0)