avm2: Split `GetLex` into `FindPropStrict` and `GetProperty`
This commit is contained in:
parent
f573f7b141
commit
f50b68abfd
|
@ -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)?;
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)?;
|
||||||
|
|
Loading…
Reference in New Issue