avm2: Merge locals better

This commit is contained in:
Lord-McSweeney 2024-06-15 15:49:45 -07:00 committed by Lord-McSweeney
parent 1389f5fa67
commit 1164dd747a
2 changed files with 36 additions and 9 deletions

View File

@ -12,7 +12,7 @@ use gc_arena::Gc;
use std::collections::HashMap;
#[allow(clippy::enum_variant_names)]
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq)]
enum NullState {
NotNull,
MaybeNull,
@ -101,6 +101,33 @@ impl<'gc> OptValue<'gc> {
|| self.class == Some(classes.boolean.inner_class_definition())
|| self.class == Some(classes.void.inner_class_definition())
}
pub fn merged_with(self, other: OptValue<'gc>) -> OptValue<'gc> {
let mut created_value = OptValue::any();
// TODO: Also check common superclasses.
if self.class == other.class {
created_value.class = self.class;
}
if self.vtable == other.vtable {
created_value.vtable = self.vtable;
}
if self.null_state == other.null_state {
created_value.null_state = self.null_state;
}
if self.contains_valid_integer && other.contains_valid_integer {
created_value.contains_valid_integer = true;
}
if self.contains_valid_unsigned && other.contains_valid_unsigned {
created_value.contains_valid_unsigned = true;
}
created_value
}
}
impl<'gc> std::fmt::Debug for OptValue<'gc> {
@ -374,14 +401,8 @@ pub fn optimize<'gc>(
} else {
for (i, target_local) in local_types.0.iter().enumerate() {
let source_local = source_local_types.at(i);
// TODO: Check superclasses, too
if let (Some(source_local_class), Some(target_local_class)) =
(source_local.class, target_local.class)
{
if source_local_class == target_local_class {
merged_types.set(i, OptValue::of_type(source_local_class));
}
}
merged_types.set(i, source_local.merged_with(*target_local));
}
}

View File

@ -43,6 +43,12 @@ pub struct VTableData<'gc> {
default_slots: Vec<Option<Value<'gc>>>,
}
impl PartialEq for VTable<'_> {
fn eq(&self, other: &Self) -> bool {
GcCell::ptr_eq(self.0, other.0)
}
}
// TODO: it might make more sense to just bind the Method to the VTable (and this its class and scope) directly
// would also be nice to somehow remove the Option-ness from `defining_class` and `scope` fields for this
// to be more intuitive and cheaper