avm2: Record all jump sources in verifier
This commit is contained in:
parent
f63641678c
commit
1389f5fa67
|
@ -5,7 +5,7 @@ use crate::avm2::multiname::Multiname;
|
|||
use crate::avm2::object::TObject;
|
||||
use crate::avm2::op::Op;
|
||||
use crate::avm2::property::Property;
|
||||
use crate::avm2::verify::JumpSources;
|
||||
use crate::avm2::verify::JumpSource;
|
||||
use crate::avm2::vtable::VTable;
|
||||
|
||||
use gc_arena::Gc;
|
||||
|
@ -202,7 +202,7 @@ pub fn optimize<'gc>(
|
|||
code: &mut Vec<Op<'gc>>,
|
||||
resolved_parameters: &[ResolvedParamConfig<'gc>],
|
||||
return_type: Option<Class<'gc>>,
|
||||
jump_targets: HashMap<i32, JumpSources>,
|
||||
jump_targets: HashMap<i32, Vec<JumpSource>>,
|
||||
) {
|
||||
// These make the code less readable
|
||||
#![allow(clippy::collapsible_if)]
|
||||
|
@ -357,12 +357,10 @@ pub fn optimize<'gc>(
|
|||
|
||||
for (i, op) in code.iter_mut().enumerate() {
|
||||
if let Some(jump_sources) = jump_targets.get(&(i as i32)) {
|
||||
if let JumpSources::Known(sources) = jump_sources {
|
||||
// Avoid handling multiple sources for now
|
||||
if sources.len() == 1 {
|
||||
if jump_sources.len() == 1 {
|
||||
if let JumpSource::JumpFrom(source_i) = jump_sources[0] {
|
||||
// We can merge the locals easily, now
|
||||
let source_i = sources[0];
|
||||
|
||||
if let Some(source_local_types) = state_map.get(&source_i) {
|
||||
let mut merged_types = initial_local_types.clone();
|
||||
assert_eq!(source_local_types.len(), local_types.len());
|
||||
|
|
|
@ -59,9 +59,9 @@ impl ByteInfo {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum JumpSources {
|
||||
Known(Vec<i32>),
|
||||
Unknown,
|
||||
pub enum JumpSource {
|
||||
JumpFrom(i32),
|
||||
ExceptionTarget,
|
||||
}
|
||||
|
||||
pub fn verify_method<'gc>(
|
||||
|
@ -400,7 +400,7 @@ pub fn verify_method<'gc>(
|
|||
|
||||
// Record a target->sources mapping of all jump
|
||||
// targets- this will be used in the optimizer.
|
||||
let mut potential_jump_targets: HashMap<i32, JumpSources> = HashMap::new();
|
||||
let mut potential_jump_targets: HashMap<i32, Vec<JumpSource>> = HashMap::new();
|
||||
|
||||
// Handle exceptions
|
||||
let mut new_exceptions = Vec::new();
|
||||
|
@ -454,9 +454,11 @@ pub fn verify_method<'gc>(
|
|||
// The large "NOTE" comment below is also relevant here
|
||||
if let Some(new_target_offset) = maybe_new_target_offset {
|
||||
// If this is a reachable target offset, insert it into the list
|
||||
// of potential jump targets. TODO: Add sources, better handle
|
||||
// the scope stack and stack being cleared after jumps
|
||||
potential_jump_targets.insert(new_target_offset, JumpSources::Unknown);
|
||||
// of potential jump targets.
|
||||
potential_jump_targets
|
||||
.entry(new_target_offset)
|
||||
.or_default()
|
||||
.push(JumpSource::ExceptionTarget);
|
||||
}
|
||||
|
||||
let new_target_offset = maybe_new_target_offset.unwrap_or(0);
|
||||
|
@ -585,25 +587,29 @@ pub fn verify_method<'gc>(
|
|||
| AbcOp::Jump { offset } => {
|
||||
let adjusted_result = adjust_jump_to_idx(i, *offset, true)?;
|
||||
*offset = adjusted_result.1;
|
||||
if let Some(jump_sources) = potential_jump_targets.get_mut(&adjusted_result.0) {
|
||||
if let JumpSources::Known(sources) = jump_sources {
|
||||
sources.push(i);
|
||||
}
|
||||
} else {
|
||||
potential_jump_targets.insert(adjusted_result.0, JumpSources::Known(vec![i]));
|
||||
}
|
||||
|
||||
potential_jump_targets
|
||||
.entry(adjusted_result.0)
|
||||
.or_default()
|
||||
.push(JumpSource::JumpFrom(i));
|
||||
}
|
||||
AbcOp::LookupSwitch(ref mut lookup_switch) => {
|
||||
// TODO: Add i to possible sources, like in the branch ops
|
||||
|
||||
let adjusted_default = adjust_jump_to_idx(i, lookup_switch.default_offset, false)?;
|
||||
lookup_switch.default_offset = adjusted_default.1;
|
||||
potential_jump_targets.insert(adjusted_default.0, JumpSources::Unknown);
|
||||
|
||||
potential_jump_targets
|
||||
.entry(adjusted_default.0)
|
||||
.or_default()
|
||||
.push(JumpSource::JumpFrom(i));
|
||||
|
||||
for case in lookup_switch.case_offsets.iter_mut() {
|
||||
let adjusted_case = adjust_jump_to_idx(i, *case, false)?;
|
||||
*case = adjusted_case.1;
|
||||
potential_jump_targets.insert(adjusted_case.0, JumpSources::Unknown);
|
||||
|
||||
potential_jump_targets
|
||||
.entry(adjusted_case.0)
|
||||
.or_default()
|
||||
.push(JumpSource::JumpFrom(i));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
Loading…
Reference in New Issue