avm2: Split `GetLex` into `FindPropStrict` and `GetProperty`

This commit is contained in:
Lord-McSweeney 2024-04-27 14:59:49 -07:00 committed by Lord-McSweeney
parent f573f7b141
commit f50b68abfd
4 changed files with 40 additions and 54 deletions

View File

@ -305,27 +305,6 @@ impl<'a, 'gc> Activation<'a, 'gc> {
} }
} }
/// Resolves a definition using either the current or outer scope of this activation.
pub fn resolve_definition(
&mut self,
name: &Multiname<'gc>,
) -> Result<Option<Value<'gc>>, Error<'gc>> {
let outer_scope = self.outer;
if let Some(obj) = search_scope_stack(self.scope_frame(), name, outer_scope.is_empty())? {
Ok(Some(obj.get_property(name, self)?))
} else if let Some(result) = outer_scope.resolve(name, self)? {
Ok(Some(result))
} else if let Some(global) = self.global_scope() {
if !global.base().has_own_property(name) {
return Ok(None);
}
return Ok(Some(global.base().get_property_local(name, self)?));
} else {
Ok(None)
}
}
/// Resolve a single parameter value. /// Resolve a single parameter value.
/// ///
/// Given an individual parameter value and the associated parameter's /// Given an individual parameter value and the associated parameter's
@ -943,7 +922,6 @@ impl<'a, 'gc> Activation<'a, 'gc> {
Op::FindDef { multiname } => self.op_find_def(*multiname), Op::FindDef { multiname } => self.op_find_def(*multiname),
Op::FindProperty { multiname } => self.op_find_property(*multiname), Op::FindProperty { multiname } => self.op_find_property(*multiname),
Op::FindPropStrict { multiname } => self.op_find_prop_strict(*multiname), Op::FindPropStrict { multiname } => self.op_find_prop_strict(*multiname),
Op::GetLex { multiname } => self.op_get_lex(*multiname),
Op::GetDescendants { multiname } => self.op_get_descendants(*multiname), Op::GetDescendants { multiname } => self.op_get_descendants(*multiname),
Op::GetSlot { index } => self.op_get_slot(*index), Op::GetSlot { index } => self.op_get_slot(*index),
Op::SetSlot { index } => self.op_set_slot(*index), Op::SetSlot { index } => self.op_set_slot(*index),
@ -1760,23 +1738,6 @@ impl<'a, 'gc> Activation<'a, 'gc> {
Ok(FrameControl::Continue) Ok(FrameControl::Continue)
} }
fn op_get_lex(
&mut self,
multiname: Gc<'gc, Multiname<'gc>>,
) -> Result<FrameControl<'gc>, Error<'gc>> {
// Verifier ensures that multiname is non-lazy
avm_debug!(self.avm2(), "Resolving {:?}", *multiname);
let found: Result<Value<'gc>, Error<'gc>> =
self.resolve_definition(&multiname)?.ok_or_else(|| {
make_reference_error(self, ReferenceErrorCode::InvalidLookup, &multiname, None)
});
self.push_stack(found?);
Ok(FrameControl::Continue)
}
fn op_get_slot(&mut self, index: u32) -> Result<FrameControl<'gc>, Error<'gc>> { fn op_get_slot(&mut self, index: u32) -> Result<FrameControl<'gc>, Error<'gc>> {
let object = self.pop_stack().coerce_to_object_or_typeerror(self, None)?; let object = self.pop_stack().coerce_to_object_or_typeerror(self, None)?;
let value = object.get_slot(index)?; let value = object.get_slot(index)?;

View File

@ -134,9 +134,6 @@ pub enum Op<'gc> {
GetGlobalSlot { GetGlobalSlot {
index: u32, index: u32,
}, },
GetLex {
multiname: Gc<'gc, Multiname<'gc>>,
},
GetLocal { GetLocal {
index: u32, index: u32,
}, },

View File

@ -730,9 +730,6 @@ pub fn optimize<'gc>(
let local_type = local_types.at(*index as usize); let local_type = local_types.at(*index as usize);
stack.push(local_type); stack.push(local_type);
} }
Op::GetLex { .. } => {
stack.push_any();
}
Op::FindPropStrict { multiname } => { Op::FindPropStrict { multiname } => {
stack.pop_for_multiname(*multiname); stack.pop_for_multiname(*multiname);

View File

@ -45,9 +45,20 @@ enum ByteInfo {
OpStart(AbcOp), OpStart(AbcOp),
OpContinue, OpContinue,
OpStartNonJumpable(AbcOp),
NotYetReached, NotYetReached,
} }
impl ByteInfo {
fn get_op(&self) -> Option<&AbcOp> {
match self {
ByteInfo::OpStart(op) | ByteInfo::OpStartNonJumpable(op) => Some(op),
_ => None,
}
}
}
pub enum JumpSources { pub enum JumpSources {
Known(Vec<i32>), Known(Vec<i32>),
Unknown, Unknown,
@ -152,7 +163,10 @@ pub fn verify_method<'gc>(
let lookedup_target_info = byte_info.get(target_position as usize); let lookedup_target_info = byte_info.get(target_position as usize);
if matches!(lookedup_target_info, Some(ByteInfo::OpContinue)) { if matches!(
lookedup_target_info,
Some(ByteInfo::OpContinue | ByteInfo::OpStartNonJumpable(_))
) {
return Err(make_error_1021(activation)); return Err(make_error_1021(activation));
} }
@ -290,7 +304,7 @@ pub fn verify_method<'gc>(
} }
} }
AbcOp::GetLex { index } | AbcOp::FindDef { index } => { AbcOp::FindDef { index } => {
let multiname = method let multiname = method
.translation_unit() .translation_unit()
.pool_maybe_uninitialized_multiname(index, &mut activation.context)?; .pool_maybe_uninitialized_multiname(index, &mut activation.context)?;
@ -304,6 +318,26 @@ pub fn verify_method<'gc>(
} }
} }
AbcOp::GetLex { index } => {
let multiname = method
.translation_unit()
.pool_maybe_uninitialized_multiname(index, &mut activation.context)?;
if multiname.has_lazy_component() {
return Err(Error::AvmError(verify_error(
activation,
"Error #1078: Illegal opcode/multiname combination.",
1078,
)?));
}
assert!(bytes_read > 1);
byte_info[previous_position as usize] =
ByteInfo::OpStart(AbcOp::FindPropStrict { index });
byte_info[(previous_position + 1) as usize] =
ByteInfo::OpStartNonJumpable(AbcOp::GetProperty { index });
}
AbcOp::GetOuterScope { index } => { AbcOp::GetOuterScope { index } => {
if activation.outer().get(index as usize).is_none() { if activation.outer().get(index as usize).is_none() {
return Err(Error::AvmError(verify_error( return Err(Error::AvmError(verify_error(
@ -349,9 +383,9 @@ pub fn verify_method<'gc>(
let mut new_code = Vec::new(); let mut new_code = Vec::new();
for (i, info) in byte_info.iter().enumerate() { for (i, info) in byte_info.iter().enumerate() {
if let ByteInfo::OpStart(c) = info { if let Some(op) = info.get_op() {
byte_offset_to_idx.insert(i, new_code.len() as i32); byte_offset_to_idx.insert(i, new_code.len() as i32);
new_code.push(c.clone()); new_code.push(op.clone());
idx_to_byte_offset.push(i); idx_to_byte_offset.push(i);
} }
} }
@ -922,11 +956,8 @@ fn resolve_op<'gc>(
Op::FindPropStrict { multiname } Op::FindPropStrict { multiname }
} }
AbcOp::GetLex { index } => { AbcOp::GetLex { .. } => {
let multiname = pool_multiname(activation, translation_unit, index)?; unreachable!("Verifier emits FindPropStrict and GetProperty instead of GetLex")
// Verifier guarantees that multiname was non-lazy
Op::GetLex { multiname }
} }
AbcOp::GetDescendants { index } => { AbcOp::GetDescendants { index } => {
let multiname = pool_multiname(activation, translation_unit, index)?; let multiname = pool_multiname(activation, translation_unit, index)?;