avm2: Use RefLock for BytecodeMethod.verified_info

This commit is contained in:
Aaron Hill 2024-09-09 11:55:09 -04:00
parent 7d1373368b
commit 6898485466
2 changed files with 16 additions and 14 deletions

View File

@ -278,7 +278,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
// Run verifier for bytecode methods // Run verifier for bytecode methods
if let Method::Bytecode(method) = method { if let Method::Bytecode(method) = method {
if method.verified_info.read().is_none() { if method.verified_info.borrow().is_none() {
BytecodeMethod::verify(method, &mut created_activation)?; BytecodeMethod::verify(method, &mut created_activation)?;
} }
} }
@ -449,11 +449,11 @@ impl<'a, 'gc> Activation<'a, 'gc> {
self.max_scope_size = (body.max_scope_depth - body.init_scope_depth) as usize; self.max_scope_size = (body.max_scope_depth - body.init_scope_depth) as usize;
// Everything is now setup for the verifier to run // Everything is now setup for the verifier to run
if method.verified_info.read().is_none() { if method.verified_info.borrow().is_none() {
BytecodeMethod::verify(method, self)?; BytecodeMethod::verify(method, self)?;
} }
let verified_info = method.verified_info.read(); let verified_info = method.verified_info.borrow();
let signature = &verified_info.as_ref().unwrap().param_config; let signature = &verified_info.as_ref().unwrap().param_config;
if user_arguments.len() > signature.len() && !has_rest_or_args { if user_arguments.len() > signature.len() && !has_rest_or_args {
@ -753,7 +753,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
// The method must be verified at this point // The method must be verified at this point
let verified_info = method.verified_info.read(); let verified_info = method.verified_info.borrow();
let verified_code = verified_info.as_ref().unwrap().parsed_code.as_slice(); let verified_code = verified_info.as_ref().unwrap().parsed_code.as_slice();
self.ip = 0; self.ip = 0;
@ -784,7 +784,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
Error::RustError(_) => return Err(error), Error::RustError(_) => return Err(error),
}; };
let verified_info = method.verified_info.read(); let verified_info = method.verified_info.borrow();
let exception_list = &verified_info.as_ref().unwrap().exceptions; let exception_list = &verified_info.as_ref().unwrap().exceptions;
// Use `coerce_to_object` so that we handle primitives correctly. // Use `coerce_to_object` so that we handle primitives correctly.
@ -1596,7 +1596,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
method: Gc<'gc, BytecodeMethod<'gc>>, method: Gc<'gc, BytecodeMethod<'gc>>,
index: Index<Exception>, index: Index<Exception>,
) -> Result<FrameControl<'gc>, Error<'gc>> { ) -> Result<FrameControl<'gc>, Error<'gc>> {
let verified_info = method.verified_info.read(); let verified_info = method.verified_info.borrow();
let exception_list = &verified_info.as_ref().unwrap().exceptions; let exception_list = &verified_info.as_ref().unwrap().exceptions;
let ex = &exception_list[index.0 as usize]; let ex = &exception_list[index.0 as usize];

View File

@ -11,7 +11,7 @@ use crate::avm2::Multiname;
use crate::string::AvmString; use crate::string::AvmString;
use crate::tag_utils::SwfMovie; use crate::tag_utils::SwfMovie;
use gc_arena::barrier::unlock; use gc_arena::barrier::unlock;
use gc_arena::lock::Lock; use gc_arena::lock::{Lock, RefLock};
use gc_arena::{Collect, Gc, GcCell, Mutation}; use gc_arena::{Collect, Gc, GcCell, Mutation};
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt; use std::fmt;
@ -135,7 +135,7 @@ pub struct BytecodeMethod<'gc> {
/// The ABC method body this function uses. /// The ABC method body this function uses.
pub abc_method_body: Option<u32>, pub abc_method_body: Option<u32>,
pub verified_info: GcCell<'gc, Option<VerifiedMethodInfo<'gc>>>, pub verified_info: RefLock<Option<VerifiedMethodInfo<'gc>>>,
/// The parameter signature of this method. /// The parameter signature of this method.
pub signature: Vec<ParamConfig<'gc>>, pub signature: Vec<ParamConfig<'gc>>,
@ -162,8 +162,6 @@ impl<'gc> BytecodeMethod<'gc> {
is_function: bool, is_function: bool,
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
) -> Result<Self, Error<'gc>> { ) -> Result<Self, Error<'gc>> {
let mc = activation.gc();
let abc = txunit.abc(); let abc = txunit.abc();
let mut signature = Vec::new(); let mut signature = Vec::new();
let mut return_type = activation.avm2().multinames.any; let mut return_type = activation.avm2().multinames.any;
@ -187,7 +185,7 @@ impl<'gc> BytecodeMethod<'gc> {
abc: txunit.abc(), abc: txunit.abc(),
abc_method: abc_method.0, abc_method: abc_method.0,
abc_method_body, abc_method_body,
verified_info: GcCell::new(mc, None), verified_info: RefLock::new(None),
signature, signature,
return_type, return_type,
is_function, is_function,
@ -233,8 +231,12 @@ impl<'gc> BytecodeMethod<'gc> {
) -> Result<(), Error<'gc>> { ) -> Result<(), Error<'gc>> {
// TODO: avmplus seems to eaglerly verify some methods // TODO: avmplus seems to eaglerly verify some methods
*this.verified_info.write(activation.context.gc_context) = *unlock!(
Some(crate::avm2::verify::verify_method(activation, this)?); Gc::write(activation.context.gc_context, this),
BytecodeMethod,
verified_info
)
.borrow_mut() = Some(crate::avm2::verify::verify_method(activation, this)?);
Ok(()) Ok(())
} }
@ -245,7 +247,7 @@ impl<'gc> BytecodeMethod<'gc> {
} }
pub fn resolved_return_type(&self) -> Option<Class<'gc>> { pub fn resolved_return_type(&self) -> Option<Class<'gc>> {
let verified_info = self.verified_info.read(); let verified_info = self.verified_info.borrow();
verified_info.as_ref().unwrap().return_type verified_info.as_ref().unwrap().return_type
} }