Skip to content

Commit 6ccb56a

Browse files
committed
avm1: Remove Gc indirection for SuperObject
1 parent e3fdfe1 commit 6ccb56a

File tree

3 files changed

+38
-26
lines changed

3 files changed

+38
-26
lines changed

core/src/avm1/function.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ impl<'gc> Avm1Function<'gc> {
219219
// TODO: `super` should only be defined if this was a method call (depth > 0?)
220220
// `f[""]()` emits a CallMethod op, causing `this` to be undefined, but `super` is a function; what is it?
221221
let zuper = this.filter(|_| !suppress).map(|this| {
222-
let zuper = NativeObject::Super(SuperObject::new(frame, this, depth));
222+
let zuper = NativeObject::Super(SuperObject::new(this, depth));
223223
Object::new_with_native(frame.strings(), None, zuper).into()
224224
});
225225

core/src/avm1/object/super_object.rs

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::avm1::function::ExecutionReason;
88
use crate::avm1::object::{search_prototype, ExecutionName};
99
use crate::avm1::{NativeObject, Object, Value};
1010
use crate::string::AvmString;
11-
use gc_arena::{Collect, Gc};
11+
use gc_arena::Collect;
1212
use ruffle_macros::istr;
1313

1414
/// Implementation of the `super` object in AS2.
@@ -18,44 +18,47 @@ use ruffle_macros::istr;
1818
/// with its parent class.
1919
#[derive(Copy, Clone, Collect)]
2020
#[collect(no_drop)]
21-
pub struct SuperObject<'gc>(Gc<'gc, SuperObjectData<'gc>>);
21+
pub struct SuperObject<'gc> {
22+
/// The object present as `this` throughout the superchain.
23+
this: Object<'gc>,
24+
25+
/// The prototype depth of the currently-executing method.
26+
depth: u8,
27+
28+
/// Adds a niche, so that enums contaning this type can use it for their discriminant.
29+
_niche: crate::utils::ZeroU8,
30+
}
2231

2332
impl fmt::Debug for SuperObject<'_> {
2433
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2534
f.debug_struct("SuperObject")
26-
.field("ptr", &Gc::as_ptr(self.0))
35+
.field("this", &self.this)
36+
.field("depth", &self.depth)
2737
.finish()
2838
}
2939
}
3040

31-
#[derive(Clone, Collect)]
32-
#[collect(no_drop)]
33-
pub struct SuperObjectData<'gc> {
34-
/// The object present as `this` throughout the superchain.
35-
this: Object<'gc>,
36-
37-
/// The prototype depth of the currently-executing method.
38-
depth: u8,
39-
}
40-
4141
impl<'gc> SuperObject<'gc> {
4242
/// Construct a `super` for an incoming stack frame.
43-
pub fn new(activation: &mut Activation<'_, 'gc>, this: Object<'gc>, depth: u8) -> Self {
44-
Self(Gc::new(activation.gc(), SuperObjectData { this, depth }))
43+
pub fn new(this: Object<'gc>, depth: u8) -> Self {
44+
Self {
45+
this,
46+
depth,
47+
_niche: Default::default(),
48+
}
4549
}
4650

4751
pub fn this(&self) -> Object<'gc> {
48-
self.0.this
52+
self.this
4953
}
5054

5155
pub fn depth(&self) -> u8 {
52-
self.0.depth
56+
self.depth
5357
}
5458

5559
pub(super) fn base_proto(&self, activation: &mut Activation<'_, 'gc>) -> Object<'gc> {
56-
let depth = self.0.depth;
57-
let mut proto = self.0.this;
58-
for _ in 0..depth {
60+
let mut proto = self.this();
61+
for _ in 0..self.depth() {
5962
proto = proto.proto(activation).coerce_to_object(activation);
6063
}
6164
proto
@@ -83,8 +86,8 @@ impl<'gc> SuperObject<'gc> {
8386
constr.as_constructor().exec(
8487
name.into(),
8588
activation,
86-
self.0.this.into(),
87-
self.0.depth + 1,
89+
self.this().into(),
90+
self.depth() + 1,
8891
args,
8992
ExecutionReason::FunctionCall,
9093
constructor,
@@ -98,7 +101,7 @@ impl<'gc> SuperObject<'gc> {
98101
activation: &mut Activation<'_, 'gc>,
99102
reason: ExecutionReason,
100103
) -> Result<Value<'gc>, Error<'gc>> {
101-
let this = self.0.this;
104+
let this = self.this();
102105
let (method, depth) =
103106
match search_prototype(self.proto(activation), name, activation, this, false)? {
104107
Some((Value::Object(method), depth)) => (method, depth),
@@ -110,7 +113,7 @@ impl<'gc> SuperObject<'gc> {
110113
ExecutionName::Dynamic(name),
111114
activation,
112115
this.into(),
113-
self.0.depth + depth + 1,
116+
self.depth() + depth + 1,
114117
args,
115118
reason,
116119
method,

core/src/utils.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use gc_arena::Gc;
1+
use gc_arena::{Collect, Gc};
22

33
pub use ruffle_macros::HasPrefixField;
44

@@ -34,3 +34,12 @@ pub unsafe trait HasPrefixField<Inner>: Sized {
3434
unsafe { Gc::cast(gc) }
3535
}
3636
}
37+
38+
/// A `u8` which is always zero. Useful to artificially introduce niches into a struct.
39+
#[derive(Copy, Clone, Collect, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
40+
#[collect(require_static)]
41+
#[repr(u8)]
42+
pub enum ZeroU8 {
43+
#[default]
44+
Zero = 0,
45+
}

0 commit comments

Comments
 (0)