From 7a7276ddaba8a66b4cffd8c166f3756c19b82598 Mon Sep 17 00:00:00 2001 From: Poytr1 Date: Thu, 14 Sep 2023 22:37:09 +0800 Subject: [PATCH 1/3] Add a multiple function test and call trace struct --- .../integration-tests/src/tests/mod.rs | 1 + .../src/tests/multi_func_tests.rs | 90 +++++++++++++++++++ .../move/move-vm/runtime/src/interpreter.rs | 34 +++++++ 3 files changed, 125 insertions(+) create mode 100644 third_party/move/move-vm/integration-tests/src/tests/multi_func_tests.rs diff --git a/third_party/move/move-vm/integration-tests/src/tests/mod.rs b/third_party/move/move-vm/integration-tests/src/tests/mod.rs index c990b267e7bb1..262bb9618a090 100644 --- a/third_party/move/move-vm/integration-tests/src/tests/mod.rs +++ b/third_party/move/move-vm/integration-tests/src/tests/mod.rs @@ -15,3 +15,4 @@ mod mutated_accounts_tests; mod nested_loop_tests; mod regression_tests; mod return_value_tests; +mod multi_func_tests; diff --git a/third_party/move/move-vm/integration-tests/src/tests/multi_func_tests.rs b/third_party/move/move-vm/integration-tests/src/tests/multi_func_tests.rs new file mode 100644 index 0000000000000..9a0180294782e --- /dev/null +++ b/third_party/move/move-vm/integration-tests/src/tests/multi_func_tests.rs @@ -0,0 +1,90 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::compiler::{as_module, compile_units}; +use move_binary_format::errors::VMResult; +use move_core_types::{ + account_address::AccountAddress, + identifier::Identifier, + language_storage::{ModuleId, TypeTag}, + value::{MoveTypeLayout, MoveValue}, +}; +use move_vm_runtime::{move_vm::MoveVM, session::SerializedReturnValues}; +use move_vm_test_utils::InMemoryStorage; +use move_vm_types::gas::UnmeteredGasMeter; + +const TEST_ADDR: AccountAddress = AccountAddress::new([42; AccountAddress::LENGTH]); + +fn run( + ty_args: Vec, + args: Vec, +) -> VMResult>> { + let code = r#" + module {{ADDR}}::M { + public fun foo(v1: u64): u64 { + bar(v1) + } + + public fun bar(v1: u64): u64 { + 1 + v1 + } + } + "#; + let code = code.replace("{{ADDR}}", &format!("0x{}", TEST_ADDR.to_hex())); + + let mut units = compile_units(&code).unwrap(); + let m = as_module(units.pop().unwrap()); + let mut blob = vec![]; + m.serialize(&mut blob).unwrap(); + + let mut storage = InMemoryStorage::new(); + let module_id = ModuleId::new(TEST_ADDR, Identifier::new("M").unwrap()); + storage.publish_or_overwrite_module(module_id.clone(), blob); + + let vm = MoveVM::new(vec![]).unwrap(); + let mut sess = vm.new_session(&storage); + + let fun_name = Identifier::new("foo").unwrap(); + + let args: Vec<_> = args + .into_iter() + .map(|val| val.simple_serialize().unwrap()) + .collect(); + + let SerializedReturnValues { + return_values, + mutable_reference_outputs: _, + } = sess.execute_function_bypass_visibility( + &module_id, + &fun_name, + ty_args, + args, + &mut UnmeteredGasMeter, + )?; + + Ok(return_values + .into_iter() + .map(|(bytes, _layout)| bytes) + .collect()) +} + +fn expect_success( + ty_args: Vec, + args: Vec, + expected_layouts: &[MoveTypeLayout], +) { + let return_vals = run(ty_args, args).unwrap(); + assert!(return_vals.len() == expected_layouts.len()); + + for (blob, layout) in return_vals.iter().zip(expected_layouts.iter()) { + MoveValue::simple_deserialize(blob, layout).unwrap(); + } +} + +#[test] +fn multi_func() { + expect_success(vec![], vec![MoveValue::U64(6)], &[ + MoveTypeLayout::U64, + ]) +} diff --git a/third_party/move/move-vm/runtime/src/interpreter.rs b/third_party/move/move-vm/runtime/src/interpreter.rs index e0cf1bd7d6b0e..20ab5bcfe23ce 100644 --- a/third_party/move/move-vm/runtime/src/interpreter.rs +++ b/third_party/move/move-vm/runtime/src/interpreter.rs @@ -31,6 +31,7 @@ use move_vm_types::{ views::TypeView, }; use std::{cmp::min, collections::VecDeque, fmt::Write, sync::Arc}; +use move_core_types::value::MoveValue; macro_rules! debug_write { ($($toks: tt)*) => { @@ -68,6 +69,8 @@ pub(crate) struct Interpreter { call_stack: CallStack, /// Whether to perform a paranoid type safety checks at runtime. paranoid_type_checks: bool, + + call_traces: CallTraces, } struct TypeWithLoader<'a, 'b> { @@ -97,6 +100,7 @@ impl Interpreter { operand_stack: Stack::new(), call_stack: CallStack::new(), paranoid_type_checks: loader.vm_config().paranoid_type_checks, + call_traces: CallTraces::new(), } .execute_main( loader, data_store, gas_meter, extensions, function, ty_args, args, @@ -1000,6 +1004,27 @@ impl CallStack { } } +struct CallTraces(Vec); + +impl CallTraces { + fn new() -> Self { + CallTraces(vec![]) + } + + fn push(&mut self, trace: CallTrace) -> Result<(), CallTrace> { + if self.0.len() < CALL_STACK_SIZE_LIMIT { + self.0.push(trace); + Ok(()) + } else { + Err(trace) + } + } + + fn pop(&mut self) -> Option { + self.0.pop() + } +} + fn check_depth_of_type(resolver: &Resolver, ty: &Type) -> PartialVMResult<()> { // Start at 1 since we always call this right before we add a new node to the value's depth. let max_depth = match resolver.loader().vm_config().max_value_nest_depth { @@ -1096,6 +1121,15 @@ struct Frame { local_tys: Vec, } +struct CallTrace { + pc: u16, + module_id: String, + func_name: String, + inputs: Vec, + outputs: Vec, + type_args: Vec, +} + /// An `ExitCode` from `execute_code_unit`. #[derive(Debug)] enum ExitCode { From 37cfe174c740fc1257930d2c42426c255986712b Mon Sep 17 00:00:00 2001 From: Poytr1 Date: Thu, 14 Sep 2023 23:15:15 +0800 Subject: [PATCH 2/3] update --- .../move/move-vm/runtime/src/interpreter.rs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/third_party/move/move-vm/runtime/src/interpreter.rs b/third_party/move/move-vm/runtime/src/interpreter.rs index 20ab5bcfe23ce..880a222ac4cc7 100644 --- a/third_party/move/move-vm/runtime/src/interpreter.rs +++ b/third_party/move/move-vm/runtime/src/interpreter.rs @@ -31,7 +31,6 @@ use move_vm_types::{ views::TypeView, }; use std::{cmp::min, collections::VecDeque, fmt::Write, sync::Arc}; -use move_core_types::value::MoveValue; macro_rules! debug_write { ($($toks: tt)*) => { @@ -124,21 +123,35 @@ impl Interpreter { args: Vec, ) -> VMResult> { let mut locals = Locals::new(function.local_count()); + let mut args_1 = vec![]; for (i, value) in args.into_iter().enumerate() { locals .store_loc( i, - value, + value.copy_value().unwrap(), loader .vm_config() .enable_invariant_violation_check_in_swap_loc, ) .map_err(|e| self.set_location(e))?; + args_1.push(value); } let mut current_frame = self .make_new_frame(loader, function, ty_args, locals) .map_err(|err| self.set_location(err))?; + self.call_traces.push(CallTrace { + pc: current_frame.pc, + module_id: "".to_string(), + func_name: current_frame.function.name().to_string(), + inputs: args_1, + outputs: vec![], + type_args: current_frame.ty_args.clone(), + }).map_err(|e| { + let err = PartialVMError::new(StatusCode::ABORTED); + let err = set_err_info!(current_frame, err); + self.maybe_core_dump(err, ¤t_frame) + })?; loop { let resolver = current_frame.resolver(loader); let exit_code = @@ -1125,8 +1138,8 @@ struct CallTrace { pc: u16, module_id: String, func_name: String, - inputs: Vec, - outputs: Vec, + inputs: Vec, + outputs: Vec, type_args: Vec, } From ad4d64d7e012278a434a09b3b3de0eab93c958c8 Mon Sep 17 00:00:00 2001 From: Poytr1 Date: Thu, 14 Sep 2023 23:18:39 +0800 Subject: [PATCH 3/3] update --- third_party/move/move-vm/runtime/src/interpreter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/move/move-vm/runtime/src/interpreter.rs b/third_party/move/move-vm/runtime/src/interpreter.rs index 880a222ac4cc7..908596b769c7b 100644 --- a/third_party/move/move-vm/runtime/src/interpreter.rs +++ b/third_party/move/move-vm/runtime/src/interpreter.rs @@ -147,7 +147,7 @@ impl Interpreter { inputs: args_1, outputs: vec![], type_args: current_frame.ty_args.clone(), - }).map_err(|e| { + }).map_err(|_e| { let err = PartialVMError::new(StatusCode::ABORTED); let err = set_err_info!(current_frame, err); self.maybe_core_dump(err, ¤t_frame)