Skip to content

Commit

Permalink
[9/n][vm-rewrite][Move] Update depth calculation calculation/caching …
Browse files Browse the repository at this point in the history
…to be threadsafe

Switching the depth calculation of types to be lazily evaluated when we
first encountered the value, coupled with shared package cache, and the
types living in this shared package cache meant that the `depth` for a
type needed to be made threadsafe since we may need to write to it in a
parallel context.

This does this by `RwLock`ing the `depth` field and then making the
changes from there.
  • Loading branch information
tzakian committed Feb 4, 2025
1 parent 1ccd302 commit 4c8450e
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 30 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub struct IntraPackageKey {
pub member_name: IdentifierKey,
}

#[derive(Debug, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[derive(Debug)]
pub struct CachedDatatype {
pub abilities: AbilitySet,
pub type_parameters: Vec<DatatypeTyParameter>,
Expand All @@ -101,7 +101,9 @@ pub struct CachedDatatype {
pub runtime_id: ModuleId,
pub module_key: IdentifierKey,
pub member_key: IdentifierKey,
pub depth: Option<DepthFormula>,
// Type depth is calculated lazily and cached here. Note that this is a read-write lock because
// this is calculated lazily and could be shared across multiple threads.
pub depth: RwLock<Option<DepthFormula>>,
pub datatype_info: Datatype,
}

Expand Down Expand Up @@ -234,32 +236,20 @@ impl VMDispatchTables {
})?
.vtable
.types;
match Arc::get_mut(&mut tys.type_at(&cache_idx.inner_pkg_key)) {
Some(datatype) => {
// This can happen if we race for filling in the depth of the datatype which is
// fine as only one will win. However, if we race for filling in the depth of
// the then the two depths must be the same.
if let Some(prev_depth) = datatype.depth.as_ref() {
if prev_depth != &depth {
return Err(PartialVMError::new(
StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR,
)
.with_message(format!(
"Depth calculation mismatch for {cache_idx:?}"
)));
}
}
datatype.depth = Some(depth);
}
None => {
// we have pending references to the `Arc` which is impossible,
// given the code that adds the `Arc` is above and no reference to
// it should exist.
// So in the spirit of not crashing we log the issue and move on leaving the
// datatypes depth as `None` -- if we try to access it later we will treat this
// as too deep.
error!("Arc<Datatype> cannot have any live reference while publishing");
let datatype_depth = &tys.type_at(&cache_idx.inner_pkg_key).depth;
let mut depth_lock = datatype_depth.write();
if let Some(prev_depth) = depth_lock.as_ref() {
// This can happen if we race for filling in the depth of the datatype which is
// fine as only one will win. However, if we race for filling in the depth of
// the then the two depths must be the same.
if prev_depth != &depth {
return Err(
PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR)
.with_message(format!("Depth calculation mismatch for {cache_idx:?}")),
);
}
} else {
*depth_lock = Some(depth);
}
}
Ok(depth_formula)
Expand All @@ -272,7 +262,7 @@ impl VMDispatchTables {
) -> PartialVMResult<DepthFormula> {
let datatype = self.resolve_type(&def_idx.clone())?;
// If we've already computed this datatypes depth, no more work remains to be done.
if let Some(form) = &datatype.depth {
if let Some(form) = datatype.depth.read().as_ref() {
return Ok(form.clone());
}
if let Some(form) = depth_cache.get(def_idx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use move_binary_format::{
internals::ModuleIndex,
};
use move_core_types::{identifier::Identifier, language_storage::ModuleId, vm_status::StatusCode};
use parking_lot::RwLock;
use std::collections::{BTreeMap, BTreeSet, HashMap};

struct PackageContext<'natives> {
Expand Down Expand Up @@ -1105,7 +1106,7 @@ fn load_module_types(
name: name.to_owned(),
defining_id,
runtime_id: module_id.clone(),
depth: None,
depth: RwLock::new(None),
datatype_info: Datatype::Struct(StructType {
fields,
field_names,
Expand Down Expand Up @@ -1181,7 +1182,7 @@ fn load_module_types(
name: name.to_owned(),
defining_id,
runtime_id: module_id.clone(),
depth: None,
depth: RwLock::new(None),
datatype_info: Datatype::Enum(EnumType {
variants,
enum_def: EnumDefinitionIndex(idx as u16),
Expand Down

0 comments on commit 4c8450e

Please sign in to comment.