Skip to content

Commit

Permalink
avm2: Use fast pointer comparison for broadcast-list dupe checks
Browse files Browse the repository at this point in the history
  • Loading branch information
adrian17 authored and Dinnerbone committed Nov 19, 2024
1 parent 43589a3 commit 3374147
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
10 changes: 6 additions & 4 deletions core/src/avm2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ impl<'gc> Avm2<'gc> {
/// behavior. This should not be called manually - `movie_clip` will
/// call it when necessary.
pub fn add_orphan_obj(&mut self, dobj: DisplayObject<'gc>) {
// Note: comparing pointers is correct because GcWeak keeps its allocation alive,
// so the pointers can't overlap by accident.
if self
.orphan_objects
.iter()
Expand Down Expand Up @@ -487,10 +489,10 @@ impl<'gc> Avm2<'gc> {
let bucket = context.avm2.broadcast_list.entry(event_name).or_default();

for entry in bucket.iter() {
if let Some(obj) = entry.upgrade(context.gc_context) {
if Object::ptr_eq(obj, object) {
return;
}
// Note: comparing pointers is correct because GcWeak keeps its allocation alive,
// so the pointers can't overlap by accident.
if entry.as_ptr() == object.as_ptr() {
return;
}
}

Expand Down
47 changes: 46 additions & 1 deletion core/src/avm2/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::display_object::DisplayObject;
use crate::html::TextFormat;
use crate::streams::NetStream;
use crate::string::{AvmString, StringContext};
use gc_arena::{Collect, Gc, Mutation};
use gc_arena::{Collect, Gc, GcWeak, Mutation};
use ruffle_macros::enum_trait_object;
use std::cell::{Ref, RefMut};
use std::fmt::Debug;
Expand Down Expand Up @@ -1484,6 +1484,51 @@ pub enum WeakObject<'gc> {
}

impl<'gc> WeakObject<'gc> {
pub fn as_ptr(self) -> *const ObjectPtr {
match self {
Self::ScriptObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::FunctionObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::PrimitiveObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::NamespaceObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::ArrayObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::StageObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::DomainObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::EventObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::DispatchObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::XmlObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::XmlListObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::RegExpObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::ByteArrayObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::LoaderInfoObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::ClassObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::VectorObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::SoundObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::SoundChannelObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::BitmapDataObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::DateObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::DictionaryObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::QNameObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::TextFormatObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::ProxyObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::ErrorObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::Stage3DObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::Context3DObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::IndexBuffer3DObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::VertexBuffer3DObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::TextureObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::Program3DObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::NetStreamObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::NetConnectionObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::ResponderObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::ShaderDataObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::SocketObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::FileReferenceObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::FontObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::LocalConnectionObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
Self::SharedObjectObject(o) => GcWeak::as_ptr(o.0) as *const ObjectPtr,
}
}

pub fn upgrade(self, mc: &Mutation<'gc>) -> Option<Object<'gc>> {
Some(match self {
Self::ScriptObject(o) => ScriptObject(o.0.upgrade(mc)?).into(),
Expand Down

0 comments on commit 3374147

Please sign in to comment.