Skip to content

Commit

Permalink
Refactoring interpreter and paranoid mode, introducing traits to allo… (
Browse files Browse the repository at this point in the history
#15350)

* Refactoring interpreter and paranoid mode, introducing traits to allow generic interpreter as well as compile time switch for the runtime type checks (formerly called paranoid mode)

* lint

* addressing comments

* addressed other

* missed null->no

* missed null->no
  • Loading branch information
ziaptos authored Nov 28, 2024
1 parent bc4364b commit 46bd0e9
Show file tree
Hide file tree
Showing 7 changed files with 1,019 additions and 927 deletions.
8 changes: 5 additions & 3 deletions third_party/move/move-vm/runtime/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright (c) The Move Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{interpreter::Interpreter, loader::Resolver, LoadedFunction};
use crate::{interpreter::InterpreterDebugInterface, loader::Resolver, LoadedFunction};
use move_binary_format::file_format::Bytecode;
use move_vm_types::values::{self, Locals};
use std::{
Expand Down Expand Up @@ -102,7 +102,7 @@ impl DebugContext {
pc: u16,
instr: &Bytecode,
resolver: &Resolver,
interp: &Interpreter,
interpreter: &dyn InterpreterDebugInterface,
) {
let instr_string = format!("{:?}", instr);
let function_string = function.name_as_pretty_string();
Expand Down Expand Up @@ -159,7 +159,9 @@ impl DebugContext {
.for_each(|(i, bp)| println!("[{}] {}", i, bp)),
DebugCommand::PrintStack => {
let mut s = String::new();
interp.debug_print_stack_trace(&mut s, resolver).unwrap();
interpreter
.debug_print_stack_trace(&mut s, resolver)
.unwrap();
println!("{}", s);
println!("Current frame: {}\n", function_string);
let code = function.code();
Expand Down
195 changes: 195 additions & 0 deletions third_party/move/move-vm/runtime/src/frame_type_cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

use crate::loader::Resolver;
use move_binary_format::{
errors::*,
file_format::{
FieldInstantiationIndex, SignatureIndex, StructDefInstantiationIndex,
StructVariantInstantiationIndex, VariantFieldInstantiationIndex,
},
};
use move_core_types::gas_algebra::NumTypeNodes;
use move_vm_types::loaded_data::runtime_types::Type;
use std::collections::BTreeMap;

#[derive(Default)]
pub(crate) struct FrameTypeCache {
struct_field_type_instantiation:
BTreeMap<StructDefInstantiationIndex, Vec<(Type, NumTypeNodes)>>,
struct_variant_field_type_instantiation:
BTreeMap<StructVariantInstantiationIndex, Vec<(Type, NumTypeNodes)>>,
struct_def_instantiation_type: BTreeMap<StructDefInstantiationIndex, (Type, NumTypeNodes)>,
struct_variant_instantiation_type:
BTreeMap<StructVariantInstantiationIndex, (Type, NumTypeNodes)>,
/// For a given field instantiation, the:
/// ((Type of the field, size of the field type) and (Type of its defining struct,
/// size of its defining struct)
field_instantiation:
BTreeMap<FieldInstantiationIndex, ((Type, NumTypeNodes), (Type, NumTypeNodes))>,
/// Same as above, bot for variant field instantiations
variant_field_instantiation:
BTreeMap<VariantFieldInstantiationIndex, ((Type, NumTypeNodes), (Type, NumTypeNodes))>,
single_sig_token_type: BTreeMap<SignatureIndex, (Type, NumTypeNodes)>,
}

impl FrameTypeCache {
#[inline(always)]
fn get_or<K: Copy + Ord + Eq, V, F>(
map: &mut BTreeMap<K, V>,
idx: K,
ty_func: F,
) -> PartialVMResult<&V>
where
F: FnOnce(K) -> PartialVMResult<V>,
{
match map.entry(idx) {
std::collections::btree_map::Entry::Occupied(entry) => Ok(entry.into_mut()),
std::collections::btree_map::Entry::Vacant(entry) => {
let v = ty_func(idx)?;
Ok(entry.insert(v))
},
}
}

#[inline(always)]
pub(crate) fn get_field_type_and_struct_type(
&mut self,
idx: FieldInstantiationIndex,
resolver: &Resolver,
ty_args: &[Type],
) -> PartialVMResult<((&Type, NumTypeNodes), (&Type, NumTypeNodes))> {
let ((field_ty, field_ty_count), (struct_ty, struct_ty_count)) =
Self::get_or(&mut self.field_instantiation, idx, |idx| {
let struct_type = resolver.field_instantiation_to_struct(idx, ty_args)?;
let struct_ty_count = NumTypeNodes::new(struct_type.num_nodes() as u64);
let field_ty = resolver.get_generic_field_ty(idx, ty_args)?;
let field_ty_count = NumTypeNodes::new(field_ty.num_nodes() as u64);
Ok(((field_ty, field_ty_count), (struct_type, struct_ty_count)))
})?;
Ok(((field_ty, *field_ty_count), (struct_ty, *struct_ty_count)))
}

pub(crate) fn get_variant_field_type_and_struct_type(
&mut self,
idx: VariantFieldInstantiationIndex,
resolver: &Resolver,
ty_args: &[Type],
) -> PartialVMResult<((&Type, NumTypeNodes), (&Type, NumTypeNodes))> {
let ((field_ty, field_ty_count), (struct_ty, struct_ty_count)) =
Self::get_or(&mut self.variant_field_instantiation, idx, |idx| {
let info = resolver.variant_field_instantiation_info_at(idx);
let struct_type = resolver.create_struct_instantiation_ty(
&info.definition_struct_type,
&info.instantiation,
ty_args,
)?;
let struct_ty_count = NumTypeNodes::new(struct_type.num_nodes() as u64);
let field_ty = resolver.instantiate_ty(
&info.uninstantiated_field_ty,
ty_args,
&info.instantiation,
)?;
let field_ty_count = NumTypeNodes::new(field_ty.num_nodes() as u64);
Ok(((field_ty, field_ty_count), (struct_type, struct_ty_count)))
})?;
Ok(((field_ty, *field_ty_count), (struct_ty, *struct_ty_count)))
}

#[inline(always)]
pub(crate) fn get_struct_type(
&mut self,
idx: StructDefInstantiationIndex,
resolver: &Resolver,
ty_args: &[Type],
) -> PartialVMResult<(&Type, NumTypeNodes)> {
let (ty, ty_count) = Self::get_or(&mut self.struct_def_instantiation_type, idx, |idx| {
let ty = resolver.get_generic_struct_ty(idx, ty_args)?;
let ty_count = NumTypeNodes::new(ty.num_nodes() as u64);
Ok((ty, ty_count))
})?;
Ok((ty, *ty_count))
}

#[inline(always)]
pub(crate) fn get_struct_variant_type(
&mut self,
idx: StructVariantInstantiationIndex,
resolver: &Resolver,
ty_args: &[Type],
) -> PartialVMResult<(&Type, NumTypeNodes)> {
let (ty, ty_count) =
Self::get_or(&mut self.struct_variant_instantiation_type, idx, |idx| {
let info = resolver.get_struct_variant_instantiation_at(idx);
let ty = resolver.create_struct_instantiation_ty(
&info.definition_struct_type,
&info.instantiation,
ty_args,
)?;
let ty_count = NumTypeNodes::new(ty.num_nodes() as u64);
Ok((ty, ty_count))
})?;
Ok((ty, *ty_count))
}

#[inline(always)]
pub(crate) fn get_struct_fields_types(
&mut self,
idx: StructDefInstantiationIndex,
resolver: &Resolver,
ty_args: &[Type],
) -> PartialVMResult<&[(Type, NumTypeNodes)]> {
Ok(Self::get_or(
&mut self.struct_field_type_instantiation,
idx,
|idx| {
Ok(resolver
.instantiate_generic_struct_fields(idx, ty_args)?
.into_iter()
.map(|ty| {
let num_nodes = NumTypeNodes::new(ty.num_nodes() as u64);
(ty, num_nodes)
})
.collect::<Vec<_>>())
},
)?)
}

#[inline(always)]
pub(crate) fn get_struct_variant_fields_types(
&mut self,
idx: StructVariantInstantiationIndex,
resolver: &Resolver,
ty_args: &[Type],
) -> PartialVMResult<&[(Type, NumTypeNodes)]> {
Ok(Self::get_or(
&mut self.struct_variant_field_type_instantiation,
idx,
|idx| {
Ok(resolver
.instantiate_generic_struct_variant_fields(idx, ty_args)?
.into_iter()
.map(|ty| {
let num_nodes = NumTypeNodes::new(ty.num_nodes() as u64);
(ty, num_nodes)
})
.collect::<Vec<_>>())
},
)?)
}

#[inline(always)]
pub(crate) fn get_signature_index_type(
&mut self,
idx: SignatureIndex,
resolver: &Resolver,
ty_args: &[Type],
) -> PartialVMResult<(&Type, NumTypeNodes)> {
let (ty, ty_count) = Self::get_or(&mut self.single_sig_token_type, idx, |idx| {
let ty = resolver.instantiate_single_type(idx, ty_args)?;
let ty_count = NumTypeNodes::new(ty.num_nodes() as u64);
Ok((ty, ty_count))
})?;
Ok((ty, *ty_count))
}
}
Loading

0 comments on commit 46bd0e9

Please sign in to comment.