diff --git a/aptos-move/aptos-gas-schedule/src/gas_schedule/move_stdlib.rs b/aptos-move/aptos-gas-schedule/src/gas_schedule/move_stdlib.rs
index c25afc6e515ba..c5063257d9ff1 100644
--- a/aptos-move/aptos-gas-schedule/src/gas_schedule/move_stdlib.rs
+++ b/aptos-move/aptos-gas-schedule/src/gas_schedule/move_stdlib.rs
@@ -3,8 +3,11 @@
//! This module defines the gas parameters for Move Stdlib.
-use crate::{gas_feature_versions::RELEASE_V1_18, gas_schedule::NativeGasParameters};
-use aptos_gas_algebra::{InternalGas, InternalGasPerByte};
+use crate::{
+ gas_feature_versions::{RELEASE_V1_18, RELEASE_V1_22},
+ gas_schedule::NativeGasParameters,
+};
+use aptos_gas_algebra::{InternalGas, InternalGasPerAbstractValueUnit, InternalGasPerByte};
crate::gas_schedule::macros::define_gas_parameters!(
MoveStdlibGasParameters,
@@ -36,5 +39,8 @@ crate::gas_schedule::macros::define_gas_parameters!(
[bcs_serialized_size_base: InternalGas, { RELEASE_V1_18.. => "bcs.serialized_size.base" }, 735],
[bcs_serialized_size_per_byte_serialized: InternalGasPerByte, { RELEASE_V1_18.. => "bcs.serialized_size.per_byte_serialized" }, 36],
[bcs_serialized_size_failure: InternalGas, { RELEASE_V1_18.. => "bcs.serialized_size.failure" }, 3676],
+
+ [mem_swap_base: InternalGas, { RELEASE_V1_22.. => "mem.swap.base" }, 367],
+ [mem_swap_per_abs_val_unit: InternalGasPerAbstractValueUnit, { RELEASE_V1_22.. => "mem.swap.per_abs_val_unit"}, 14],
]
);
diff --git a/aptos-move/aptos-gas-schedule/src/ver.rs b/aptos-move/aptos-gas-schedule/src/ver.rs
index f798c42b40145..d958276339a46 100644
--- a/aptos-move/aptos-gas-schedule/src/ver.rs
+++ b/aptos-move/aptos-gas-schedule/src/ver.rs
@@ -69,7 +69,7 @@
/// global operations.
/// - V1
/// - TBA
-pub const LATEST_GAS_FEATURE_VERSION: u64 = gas_feature_versions::RELEASE_V1_21;
+pub const LATEST_GAS_FEATURE_VERSION: u64 = gas_feature_versions::RELEASE_V1_22;
pub mod gas_feature_versions {
pub const RELEASE_V1_8: u64 = 11;
@@ -86,4 +86,5 @@ pub mod gas_feature_versions {
pub const RELEASE_V1_19: u64 = 23;
pub const RELEASE_V1_20: u64 = 24;
pub const RELEASE_V1_21: u64 = 25;
+ pub const RELEASE_V1_22: u64 = 26;
}
diff --git a/aptos-move/e2e-move-tests/src/tests/code_publishing.data/pack_stdlib/sources/mem.move b/aptos-move/e2e-move-tests/src/tests/code_publishing.data/pack_stdlib/sources/mem.move
new file mode 120000
index 0000000000000..13c1b4e1d1a8f
--- /dev/null
+++ b/aptos-move/e2e-move-tests/src/tests/code_publishing.data/pack_stdlib/sources/mem.move
@@ -0,0 +1 @@
+../../../../../../framework/move-stdlib/sources/mem.move
\ No newline at end of file
diff --git a/aptos-move/e2e-move-tests/src/tests/code_publishing.data/pack_stdlib_incompat/sources/mem.move b/aptos-move/e2e-move-tests/src/tests/code_publishing.data/pack_stdlib_incompat/sources/mem.move
new file mode 120000
index 0000000000000..13c1b4e1d1a8f
--- /dev/null
+++ b/aptos-move/e2e-move-tests/src/tests/code_publishing.data/pack_stdlib_incompat/sources/mem.move
@@ -0,0 +1 @@
+../../../../../../framework/move-stdlib/sources/mem.move
\ No newline at end of file
diff --git a/aptos-move/framework/move-stdlib/doc/mem.md b/aptos-move/framework/move-stdlib/doc/mem.md
new file mode 100644
index 0000000000000..cce483a926275
--- /dev/null
+++ b/aptos-move/framework/move-stdlib/doc/mem.md
@@ -0,0 +1,113 @@
+
+
+
+# Module `0x1::mem`
+
+Module with methods for safe memory manipulation.
+I.e. swapping/replacing non-copyable/non-droppable types.
+
+
+- [Function `swap`](#0x1_mem_swap)
+- [Function `replace`](#0x1_mem_replace)
+- [Specification](#@Specification_0)
+ - [Function `swap`](#@Specification_0_swap)
+ - [Function `replace`](#@Specification_0_replace)
+
+
+
+
+
+
+
+
+## Function `swap`
+
+Swap contents of two passed mutable references.
+
+
+public fun swap<T>(left: &mut T, right: &mut T)
+
+
+
+
+
+Implementation
+
+
+public native fun swap<T>(left: &mut T, right: &mut T);
+
+
+
+
+
+
+
+
+## Function `replace`
+
+Replace value reference points to with the given new value,
+and return value it had before.
+
+
+public fun replace<T>(ref: &mut T, new: T): T
+
+
+
+
+
+Implementation
+
+
+public fun replace<T>(ref: &mut T, new: T): T {
+ swap(ref, &mut new);
+ new
+}
+
+
+
+
+
+
+
+
+## Specification
+
+
+
+
+### Function `swap`
+
+
+public fun swap<T>(left: &mut T, right: &mut T)
+
+
+
+
+
+pragma opaque;
+aborts_if false;
+ensures right == old(left);
+ensures left == old(right);
+
+
+
+
+
+
+### Function `replace`
+
+
+public fun replace<T>(ref: &mut T, new: T): T
+
+
+
+
+
+pragma opaque;
+aborts_if false;
+ensures result == old(ref);
+ensures ref == new;
+
+
+
+[move-book]: https://aptos.dev/move/book/SUMMARY
diff --git a/aptos-move/framework/move-stdlib/doc/overview.md b/aptos-move/framework/move-stdlib/doc/overview.md
index 8eb0c67f05113..649873e8ab2f5 100644
--- a/aptos-move/framework/move-stdlib/doc/overview.md
+++ b/aptos-move/framework/move-stdlib/doc/overview.md
@@ -20,6 +20,7 @@ For on overview of the Move language, see the [Move Book][move-book].
- [`0x1::features`](features.md#0x1_features)
- [`0x1::fixed_point32`](fixed_point32.md#0x1_fixed_point32)
- [`0x1::hash`](hash.md#0x1_hash)
+- [`0x1::mem`](mem.md#0x1_mem)
- [`0x1::option`](option.md#0x1_option)
- [`0x1::signer`](signer.md#0x1_signer)
- [`0x1::string`](string.md#0x1_string)
diff --git a/aptos-move/framework/move-stdlib/sources/mem.move b/aptos-move/framework/move-stdlib/sources/mem.move
new file mode 100644
index 0000000000000..98758c43eba38
--- /dev/null
+++ b/aptos-move/framework/move-stdlib/sources/mem.move
@@ -0,0 +1,27 @@
+/// Module with methods for safe memory manipulation.
+/// I.e. swapping/replacing non-copyable/non-droppable types.
+module std::mem {
+ /// Swap contents of two passed mutable references.
+ public native fun swap(left: &mut T, right: &mut T);
+
+ /// Replace value reference points to with the given new value,
+ /// and return value it had before.
+ public fun replace(ref: &mut T, new: T): T {
+ swap(ref, &mut new);
+ new
+ }
+
+ spec swap(left: &mut T, right: &mut T) {
+ pragma opaque;
+ aborts_if false;
+ ensures right == old(left);
+ ensures left == old(right);
+ }
+
+ spec replace(ref: &mut T, new: T): T {
+ pragma opaque;
+ aborts_if false;
+ ensures result == old(ref);
+ ensures ref == new;
+ }
+}
diff --git a/aptos-move/framework/move-stdlib/src/natives/mem.rs b/aptos-move/framework/move-stdlib/src/natives/mem.rs
new file mode 100644
index 0000000000000..e13dccfd20ab3
--- /dev/null
+++ b/aptos-move/framework/move-stdlib/src/natives/mem.rs
@@ -0,0 +1,75 @@
+// Copyright © Aptos Foundation
+// SPDX-License-Identifier: Apache-2.0
+
+// Copyright (c) The Diem Core Contributors
+// Copyright (c) The Move Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+//! Implementation of native functions for utf8 strings.
+
+use aptos_gas_schedule::gas_params::natives::move_stdlib::{
+ MEM_SWAP_BASE, MEM_SWAP_PER_ABS_VAL_UNIT,
+};
+use aptos_native_interface::{
+ safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeError,
+ SafeNativeResult,
+};
+use move_core_types::vm_status::StatusCode;
+use move_vm_runtime::native_functions::NativeFunction;
+use move_vm_types::{
+ loaded_data::runtime_types::Type,
+ natives::function::PartialVMError,
+ values::{Reference, Value},
+};
+use smallvec::{smallvec, SmallVec};
+use std::collections::VecDeque;
+
+/***************************************************************************************************
+ * native fun native_swap
+ *
+ * gas cost: MEM_SWAP_BASE + MEM_SWAP_PER_ABS_VAL_UNIT * abstract_size_of_arguments
+ *
+ **************************************************************************************************/
+fn native_swap(
+ context: &mut SafeNativeContext,
+ _ty_args: Vec,
+ mut args: VecDeque,
+) -> SafeNativeResult> {
+ debug_assert!(args.len() == 2);
+
+ if args.len() != 2 {
+ return Err(SafeNativeError::InvariantViolation(PartialVMError::new(
+ StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR,
+ )));
+ }
+
+ let cost = MEM_SWAP_BASE
+ + MEM_SWAP_PER_ABS_VAL_UNIT
+ * (context.abs_val_size(&args[0]) + context.abs_val_size(&args[1]));
+ context.charge(cost)?;
+
+ let ref1 = safely_pop_arg!(args, Reference);
+ let ref0 = safely_pop_arg!(args, Reference);
+
+ ref0.swap_ref(|value0| {
+ let mut value1_opt = Option::None;
+ ref1.swap_ref(|value1| {
+ value1_opt = Option::Some(value1);
+ Ok(value0)
+ })?;
+ Ok(value1_opt.unwrap())
+ })?;
+
+ Ok(smallvec![])
+}
+
+/***************************************************************************************************
+ * module
+ **************************************************************************************************/
+pub fn make_all(
+ builder: &SafeNativeBuilder,
+) -> impl Iterator- + '_ {
+ let natives = [("swap", native_swap as RawSafeNative)];
+
+ builder.make_named_natives(natives)
+}
diff --git a/aptos-move/framework/move-stdlib/src/natives/mod.rs b/aptos-move/framework/move-stdlib/src/natives/mod.rs
index 56b37bd332960..24c995f7e9cec 100644
--- a/aptos-move/framework/move-stdlib/src/natives/mod.rs
+++ b/aptos-move/framework/move-stdlib/src/natives/mod.rs
@@ -7,6 +7,7 @@
pub mod bcs;
pub mod hash;
+pub mod mem;
pub mod signer;
pub mod string;
#[cfg(feature = "testing")]
@@ -33,6 +34,7 @@ pub fn all_natives(
builder.with_incremental_gas_charging(false, |builder| {
add_natives!("bcs", bcs::make_all(builder));
add_natives!("hash", hash::make_all(builder));
+ add_natives!("mem", mem::make_all(builder));
add_natives!("signer", signer::make_all(builder));
add_natives!("string", string::make_all(builder));
#[cfg(feature = "testing")]
diff --git a/aptos-move/framework/move-stdlib/tests/mem_tests.move b/aptos-move/framework/move-stdlib/tests/mem_tests.move
new file mode 100644
index 0000000000000..14144ee4b3513
--- /dev/null
+++ b/aptos-move/framework/move-stdlib/tests/mem_tests.move
@@ -0,0 +1,65 @@
+#[test_only]
+module std::mem_tests {
+ use std::vector;
+ use std::mem::{swap, replace};
+
+ #[test]
+ fun test_swap_ints() {
+ let a = 1;
+ let b = 2;
+ let v = vector[3, 4, 5, 6];
+
+ swap(&mut a, &mut b);
+ assert!(a == 2, 0);
+ assert!(b == 1, 1);
+
+ swap(&mut a, vector::borrow_mut(&mut v, 0));
+ assert!(a == 3, 0);
+ assert!(vector::borrow(&v, 0) == &2, 1);
+
+ swap(vector::borrow_mut(&mut v, 2), &mut a);
+ assert!(a == 5, 0);
+ assert!(vector::borrow(&v, 2) == &3, 1);
+ }
+
+
+ #[test]
+ fun test_replace_ints() {
+ let a = 1;
+ let b = 2;
+
+ assert!(replace(&mut a, b) == 1, 0);
+ assert!(a == 2, 1);
+ }
+
+ #[test_only]
+ struct SomeStruct has drop {
+ f: u64,
+ v: vector,
+ }
+
+ #[test]
+ fun test_swap_struct() {
+ let a = 1;
+ let s1 = SomeStruct { f: 2, v: vector[3, 4]};
+ let s2 = SomeStruct { f: 5, v: vector[6, 7]};
+ let vs = vector[SomeStruct { f: 8, v: vector[9, 10]}, SomeStruct { f: 11, v: vector[12, 13]}];
+
+
+ swap(&mut s1, &mut s2);
+ assert!(&s1 == &SomeStruct { f: 5, v: vector[6, 7]}, 0);
+ assert!(&s2 == &SomeStruct { f: 2, v: vector[3, 4]}, 1);
+
+ swap(&mut s1.f, &mut a);
+ assert!(s1.f == 1, 2);
+ assert!(a == 5, 3);
+
+ swap(&mut s1.f, vector::borrow_mut(&mut s1.v, 0));
+ assert!(s1.f == 6, 4);
+ assert!(vector::borrow(&s1.v, 0) == &1, 5);
+
+ swap(&mut s2, vector::borrow_mut(&mut vs, 0));
+ assert!(&s2 == &SomeStruct { f: 8, v: vector[9, 10]}, 6);
+ assert!(vector::borrow(&vs, 0) == &SomeStruct { f: 2, v: vector[3, 4]}, 7);
+ }
+}
diff --git a/execution/executor/tests/internal_indexer_test.rs b/execution/executor/tests/internal_indexer_test.rs
index ba6b004de55c9..52713351abde7 100644
--- a/execution/executor/tests/internal_indexer_test.rs
+++ b/execution/executor/tests/internal_indexer_test.rs
@@ -20,7 +20,7 @@ use aptos_types::{
account_config::aptos_test_root_address,
block_metadata::BlockMetadata,
chain_id::ChainId,
- state_store::state_key::prefix::StateKeyPrefix,
+ state_store::state_key::{prefix::StateKeyPrefix, StateKey},
test_helpers::transaction_test_helpers::TEST_BLOCK_EXECUTOR_ONCHAIN_CONFIG,
transaction::{
signature_verified_transaction::into_signature_verified_block,
@@ -28,8 +28,9 @@ use aptos_types::{
WriteSetPayload,
},
};
+use move_core_types::{ident_str, language_storage::StructTag};
use rand::SeedableRng;
-use std::sync::Arc;
+use std::{fmt::Debug, str::FromStr, sync::Arc};
const B: u64 = 1_000_000_000;
@@ -192,6 +193,208 @@ fn test_db_indexer_data() {
total_version,
)
.unwrap();
- let address_one_kv_res: Vec<_> = address_one_kv_iter.collect();
- assert_eq!(address_one_kv_res.len(), 152);
+ let address_one_kv_res = address_one_kv_iter.collect::, _>>().unwrap();
+
+ let (code, resources): (Vec<_>, Vec<_>) = address_one_kv_res
+ .into_iter()
+ .map(|(s, _)| s)
+ .partition(|s| s.is_aptos_code());
+
+ let expected_code = vec![
+ ident_str!("acl"),
+ ident_str!("any"),
+ ident_str!("bcs"),
+ ident_str!("dkg"),
+ ident_str!("mem"),
+ ident_str!("code"),
+ ident_str!("coin"),
+ ident_str!("guid"),
+ ident_str!("hash"),
+ ident_str!("jwks"),
+ ident_str!("util"),
+ ident_str!("block"),
+ ident_str!("debug"),
+ ident_str!("error"),
+ ident_str!("event"),
+ ident_str!("stake"),
+ ident_str!("table"),
+ ident_str!("math64"),
+ ident_str!("object"),
+ ident_str!("option"),
+ ident_str!("signer"),
+ ident_str!("string"),
+ ident_str!("vector"),
+ ident_str!("voting"),
+ ident_str!("account"),
+ ident_str!("ed25519"),
+ ident_str!("genesis"),
+ ident_str!("math128"),
+ ident_str!("version"),
+ ident_str!("vesting"),
+ ident_str!("bls12381"),
+ ident_str!("chain_id"),
+ ident_str!("features"),
+ ident_str!("from_bcs"),
+ ident_str!("pool_u64"),
+ ident_str!("secp256k1"),
+ ident_str!("timestamp"),
+ ident_str!("type_info"),
+ ident_str!("aggregator"),
+ ident_str!("aptos_coin"),
+ ident_str!("aptos_hash"),
+ ident_str!("big_vector"),
+ ident_str!("bit_vector"),
+ ident_str!("capability"),
+ ident_str!("comparator"),
+ ident_str!("math_fixed"),
+ ident_str!("randomness"),
+ ident_str!("simple_map"),
+ ident_str!("smart_table"),
+ ident_str!("storage_gas"),
+ ident_str!("chain_status"),
+ ident_str!("copyable_any"),
+ ident_str!("gas_schedule"),
+ ident_str!("managed_coin"),
+ ident_str!("math_fixed64"),
+ ident_str!("ristretto255"),
+ ident_str!("smart_vector"),
+ ident_str!("string_utils"),
+ ident_str!("aggregator_v2"),
+ ident_str!("aptos_account"),
+ ident_str!("bn254_algebra"),
+ ident_str!("config_buffer"),
+ ident_str!("create_signer"),
+ ident_str!("fixed_point32"),
+ ident_str!("fixed_point64"),
+ ident_str!("function_info"),
+ ident_str!("multi_ed25519"),
+ ident_str!("staking_proxy"),
+ ident_str!("state_storage"),
+ ident_str!("crypto_algebra"),
+ ident_str!("fungible_asset"),
+ ident_str!("staking_config"),
+ ident_str!("delegation_pool"),
+ ident_str!("keyless_account"),
+ ident_str!("reconfiguration"),
+ ident_str!("transaction_fee"),
+ ident_str!("aptos_governance"),
+ ident_str!("bls12381_algebra"),
+ ident_str!("consensus_config"),
+ ident_str!("execution_config"),
+ ident_str!("multisig_account"),
+ ident_str!("pool_u64_unbound"),
+ ident_str!("resource_account"),
+ ident_str!("staking_contract"),
+ ident_str!("system_addresses"),
+ ident_str!("randomness_config"),
+ ident_str!("table_with_length"),
+ ident_str!("aggregator_factory"),
+ ident_str!("governance_proposal"),
+ ident_str!("optional_aggregator"),
+ ident_str!("transaction_context"),
+ ident_str!("jwk_consensus_config"),
+ ident_str!("ristretto255_elgamal"),
+ ident_str!("reconfiguration_state"),
+ ident_str!("ristretto255_pedersen"),
+ ident_str!("object_code_deployment"),
+ ident_str!("primary_fungible_store"),
+ ident_str!("transaction_validation"),
+ ident_str!("randomness_api_v0_config"),
+ ident_str!("randomness_config_seqnum"),
+ ident_str!("reconfiguration_with_dkg"),
+ ident_str!("validator_consensus_info"),
+ ident_str!("ristretto255_bulletproofs"),
+ ident_str!("dispatchable_fungible_asset"),
+ ]
+ .into_iter()
+ .map(|module| StateKey::module(&AccountAddress::ONE, module))
+ .collect::>();
+
+ assert_vec_eq(&code, &expected_code);
+
+ let expected_resources = vec![
+ (false, "0x1::dkg::DKGState"),
+ (false, "0x1::jwks::Patches"),
+ (false, "0x1::account::Account"),
+ (false, "0x1::version::Version"),
+ (false, "0x1::jwks::PatchedJWKs"),
+ (false, "0x1::chain_id::ChainId"),
+ (false, "0x1::coin::SupplyConfig"),
+ (false, "0x1::jwks::ObservedJWKs"),
+ (false, "0x1::features::Features"),
+ (false, "0x1::stake::ValidatorSet"),
+ (false, "0x1::block::BlockResource"),
+ (false, "0x1::block::CommitHistory"),
+ (false, "0x1::code::PackageRegistry"),
+ (true, "0x1::keyless_account::Group"),
+ (false, "0x1::coin::CoinConversionMap"),
+ (false, "0x1::storage_gas::StorageGas"),
+ (false, "0x1::stake::ValidatorPerformance"),
+ (false, "0x1::account::OriginatingAddress"),
+ (false, "0x1::gas_schedule::GasScheduleV2"),
+ (false, "0x1::jwks::SupportedOIDCProviders"),
+ (false, "0x1::stake::AptosCoinCapabilities"),
+ (false, "0x1::reconfiguration_state::State"),
+ (false, "0x1::version::SetVersionCapability"),
+ (false, "0x1::storage_gas::StorageGasConfig"),
+ (false, "0x1::config_buffer::PendingConfigs"),
+ (false, "0x1::staking_config::StakingConfig"),
+ (false, "0x1::randomness::PerBlockRandomness"),
+ (false, "0x1::chain_status::GenesisEndMarker"),
+ (false, "0x1::reconfiguration::Configuration"),
+ (false, "0x1::aptos_governance::VotingRecords"),
+ (false, "0x1::state_storage::StateStorageUsage"),
+ (false, "0x1::consensus_config::ConsensusConfig"),
+ (false, "0x1::execution_config::ExecutionConfig"),
+ (false, "0x1::timestamp::CurrentTimeMicroseconds"),
+ (false, "0x1::aptos_governance::GovernanceConfig"),
+ (false, "0x1::aptos_governance::GovernanceEvents"),
+ (false, "0x1::randomness_config::RandomnessConfig"),
+ (false, "0x1::aggregator_factory::AggregatorFactory"),
+ (false, "0x1::transaction_fee::AptosCoinCapabilities"),
+ (false, "0x1::transaction_fee::AptosCoinMintCapability"),
+ (false, "0x1::jwk_consensus_config::JWKConsensusConfig"),
+ (false, "0x1::aptos_governance::ApprovedExecutionHashes"),
+ (false, "0x1::aptos_governance::GovernanceResponsbility"),
+ (false, "0x1::randomness_api_v0_config::RequiredGasDeposit"),
+ (false, "0x1::transaction_validation::TransactionValidation"),
+ (
+ false,
+ "0x1::randomness_api_v0_config::AllowCustomMaxGasFlag",
+ ),
+ (
+ false,
+ "0x1::randomness_config_seqnum::RandomnessConfigSeqNum",
+ ),
+ (false, "0x1::coin::CoinInfo<0x1::aptos_coin::AptosCoin>"),
+ (
+ false,
+ "0x1::voting::VotingForum<0x1::governance_proposal::GovernanceProposal>",
+ ),
+ ]
+ .into_iter()
+ .map(|(rg, struct_tag)| {
+ if rg {
+ StateKey::resource_group(
+ &AccountAddress::ONE,
+ &StructTag::from_str(struct_tag).unwrap(),
+ )
+ } else {
+ StateKey::resource(
+ &AccountAddress::ONE,
+ &StructTag::from_str(struct_tag).unwrap(),
+ )
+ .unwrap()
+ }
+ })
+ .collect::>();
+
+ assert_vec_eq(&resources, &expected_resources);
+}
+
+fn assert_vec_eq(left: &[T], right: &[T]) {
+ for i in 0..left.len().min(right.len()) {
+ assert_eq!(left[i], right[i], "difference at position {}", i);
+ }
+ assert_eq!(left.len(), right.len(), "difference at last element");
}
diff --git a/third_party/move/move-vm/types/src/values/values_impl.rs b/third_party/move/move-vm/types/src/values/values_impl.rs
index 006c16d6b9dd1..9db5b3a678ef7 100644
--- a/third_party/move/move-vm/types/src/values/values_impl.rs
+++ b/third_party/move/move-vm/types/src/values/values_impl.rs
@@ -903,6 +903,81 @@ impl Reference {
}
}
+/**************************************************************************************
+ *
+ * Swap reference (Move)
+ *
+ * Implementation of the Move operation to swap contents of a reference.
+ *
+ *************************************************************************************/
+
+impl ContainerRef {
+ pub fn swap_ref(self, swap_with: F) -> PartialVMResult<()>
+ where
+ F: FnOnce(Value) -> PartialVMResult,
+ {
+ // same as read_ref, but without consuming self.
+ // But safe because even though we copy here, and temporarily leave a duplicate inside,
+ // we replace it in write_ref below.
+ let old_value = Value(ValueImpl::Container(self.container().copy_value()?));
+ self.write_ref(swap_with(old_value)?)?;
+
+ Ok(())
+ }
+}
+
+impl IndexedRef {
+ pub fn swap_ref(self, swap_with: F) -> PartialVMResult<()>
+ where
+ F: FnOnce(Value) -> PartialVMResult,
+ {
+ use Container::*;
+
+ // same as read_ref, but without consuming self.
+ // But safe because even though we copy here, and temporarily leave a duplicate inside,
+ // we replace it in write_ref below.
+ let old_value = Value(match self.container_ref.container() {
+ Vec(r) => r.borrow()[self.idx].copy_value()?,
+ Struct(r) => r.borrow()[self.idx].copy_value()?,
+
+ VecU8(r) => ValueImpl::U8(r.borrow()[self.idx]),
+ VecU16(r) => ValueImpl::U16(r.borrow()[self.idx]),
+ VecU32(r) => ValueImpl::U32(r.borrow()[self.idx]),
+ VecU64(r) => ValueImpl::U64(r.borrow()[self.idx]),
+ VecU128(r) => ValueImpl::U128(r.borrow()[self.idx]),
+ VecU256(r) => ValueImpl::U256(r.borrow()[self.idx]),
+ VecBool(r) => ValueImpl::Bool(r.borrow()[self.idx]),
+ VecAddress(r) => ValueImpl::Address(r.borrow()[self.idx]),
+
+ Locals(r) => r.borrow()[self.idx].copy_value()?,
+ });
+
+ self.write_ref(swap_with(old_value)?)?;
+ Ok(())
+ }
+}
+
+impl ReferenceImpl {
+ pub fn swap_ref(self, swap_with: F) -> PartialVMResult<()>
+ where
+ F: FnOnce(Value) -> PartialVMResult,
+ {
+ match self {
+ Self::ContainerRef(r) => r.swap_ref(swap_with),
+ Self::IndexedRef(r) => r.swap_ref(swap_with),
+ }
+ }
+}
+
+impl Reference {
+ pub fn swap_ref(self, swap_with: F) -> PartialVMResult<()>
+ where
+ F: FnOnce(Value) -> PartialVMResult,
+ {
+ self.0.swap_ref(swap_with)
+ }
+}
+
/***************************************************************************************
*
* Borrows (Move)