Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[move][stdlib] Implement mem::swap native move call #14786

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -3,7 +3,10 @@

//! This module defines the gas parameters for Move Stdlib.

use crate::{gas_feature_versions::RELEASE_V1_18, gas_schedule::NativeGasParameters};
use crate::{
gas_feature_versions::{RELEASE_V1_18, RELEASE_V1_24},
gas_schedule::NativeGasParameters,
};
use aptos_gas_algebra::{InternalGas, InternalGasPerByte};

crate::gas_schedule::macros::define_gas_parameters!(
Expand Down Expand Up @@ -36,5 +39,7 @@ 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_24.. => "mem.swap.base" }, 1500],
]
);
2 changes: 1 addition & 1 deletion aptos-move/aptos-gas-schedule/src/ver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
/// global operations.
/// - V1
/// - TBA
pub const LATEST_GAS_FEATURE_VERSION: u64 = gas_feature_versions::RELEASE_V1_23;
pub const LATEST_GAS_FEATURE_VERSION: u64 = gas_feature_versions::RELEASE_V1_24;

pub mod gas_feature_versions {
pub const RELEASE_V1_8: u64 = 11;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ pub enum FeatureFlag {
TransactionSimulationEnhancement,
CollectionOwner,
EnableLoaderV2,
NativeMemoryOperations,
georgemitenkov marked this conversation as resolved.
Show resolved Hide resolved
}

fn generate_features_blob(writer: &CodeWriter, data: &[u64]) {
Expand Down Expand Up @@ -349,6 +350,7 @@ impl From<FeatureFlag> for AptosFeatureFlag {
},
FeatureFlag::CollectionOwner => AptosFeatureFlag::COLLECTION_OWNER,
FeatureFlag::EnableLoaderV2 => AptosFeatureFlag::ENABLE_LOADER_V2,
FeatureFlag::NativeMemoryOperations => AptosFeatureFlag::NATIVE_MEMORY_OPERATIONS,
}
}
}
Expand Down Expand Up @@ -493,6 +495,7 @@ impl From<AptosFeatureFlag> for FeatureFlag {
},
AptosFeatureFlag::COLLECTION_OWNER => FeatureFlag::CollectionOwner,
AptosFeatureFlag::ENABLE_LOADER_V2 => FeatureFlag::EnableLoaderV2,
AptosFeatureFlag::NATIVE_MEMORY_OPERATIONS => FeatureFlag::NativeMemoryOperations,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions aptos-move/framework/move-stdlib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ publish = false
[dependencies]
aptos-gas-schedule = { workspace = true }
aptos-native-interface = { workspace = true }
aptos-types = { workspace = true }
move-core-types = { path = "../../../third_party/move/move-core/types" }
move-vm-runtime = { path = "../../../third_party/move/move-vm/runtime" }
move-vm-types = { path = "../../../third_party/move/move-vm/types" }
Expand Down
112 changes: 112 additions & 0 deletions aptos-move/framework/move-stdlib/doc/mem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@

<a id="0x1_mem"></a>

# Module `0x1::mem`

Module with methods for safe memory manipulation.


- [Function `swap`](#0x1_mem_swap)
- [Function `replace`](#0x1_mem_replace)
- [Specification](#@Specification_0)
- [Function `swap`](#@Specification_0_swap)
- [Function `replace`](#@Specification_0_replace)


<pre><code></code></pre>



<a id="0x1_mem_swap"></a>

## Function `swap`

Swap contents of two passed mutable references.


<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="mem.md#0x1_mem_swap">swap</a>&lt;T&gt;(left: &<b>mut</b> T, right: &<b>mut</b> T)
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b>(<b>friend</b>) <b>native</b> <b>fun</b> <a href="mem.md#0x1_mem_swap">swap</a>&lt;T&gt;(left: &<b>mut</b> T, right: &<b>mut</b> T);
</code></pre>



</details>

<a id="0x1_mem_replace"></a>

## Function `replace`

Replace the value reference points to with the given new value,
and return the value it had before.


<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="mem.md#0x1_mem_replace">replace</a>&lt;T&gt;(ref: &<b>mut</b> T, new: T): T
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="mem.md#0x1_mem_replace">replace</a>&lt;T&gt;(ref: &<b>mut</b> T, new: T): T {
<a href="mem.md#0x1_mem_swap">swap</a>(ref, &<b>mut</b> new);
new
}
</code></pre>



</details>

<a id="@Specification_0"></a>

## Specification


<a id="@Specification_0_swap"></a>

### Function `swap`


<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="mem.md#0x1_mem_swap">swap</a>&lt;T&gt;(left: &<b>mut</b> T, right: &<b>mut</b> T)
</code></pre>




<pre><code><b>pragma</b> opaque;
<b>aborts_if</b> <b>false</b>;
<b>ensures</b> right == <b>old</b>(left);
<b>ensures</b> left == <b>old</b>(right);
</code></pre>



<a id="@Specification_0_replace"></a>

### Function `replace`


<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="mem.md#0x1_mem_replace">replace</a>&lt;T&gt;(ref: &<b>mut</b> T, new: T): T
</code></pre>




<pre><code><b>pragma</b> opaque;
<b>aborts_if</b> <b>false</b>;
<b>ensures</b> result == <b>old</b>(ref);
<b>ensures</b> ref == new;
</code></pre>


[move-book]: https://aptos.dev/move/book/SUMMARY
1 change: 1 addition & 0 deletions aptos-move/framework/move-stdlib/doc/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
31 changes: 31 additions & 0 deletions aptos-move/framework/move-stdlib/sources/mem.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/// Module with methods for safe memory manipulation.
module std::mem {
// TODO - functions here are `public(friend)` here for one release,
// and to be changed to `public` one release later.
#[test_only]
friend std::mem_tests;

/// Swap contents of two passed mutable references.
public(friend) native fun swap<T>(left: &mut T, right: &mut T);

/// Replace the value reference points to with the given new value,
/// and return the value it had before.
public(friend) fun replace<T>(ref: &mut T, new: T): T {
swap(ref, &mut new);
new
}

spec swap<T>(left: &mut T, right: &mut T) {
pragma opaque;
aborts_if false;
ensures right == old(left);
ensures left == old(right);
}

spec replace<T>(ref: &mut T, new: T): T {
pragma opaque;
aborts_if false;
ensures result == old(ref);
ensures ref == new;
}
}
64 changes: 64 additions & 0 deletions aptos-move/framework/move-stdlib/src/natives/mem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

//! Implementation of native functions for memory manipulation.

use aptos_gas_schedule::gas_params::natives::move_stdlib::MEM_SWAP_BASE;
use aptos_native_interface::{
safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeError,
SafeNativeResult,
};
use aptos_types::error;
use move_vm_runtime::native_functions::NativeFunction;
use move_vm_types::{
loaded_data::runtime_types::Type,
values::{Reference, Value},
};
use smallvec::{smallvec, SmallVec};
use std::collections::VecDeque;

/// The feature is not enabled.
pub const EFEATURE_NOT_ENABLED: u64 = 1;

/***************************************************************************************************
* native fun native_swap
*
* gas cost: MEM_SWAP_BASE
*
**************************************************************************************************/
fn native_swap(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a comment that function pre-condition is that the two references are not the same.

context: &mut SafeNativeContext,
_ty_args: Vec<Type>,
mut args: VecDeque<Value>,
) -> SafeNativeResult<SmallVec<[Value; 1]>> {
if !context
.get_feature_flags()
.is_native_memory_operations_enabled()
{
return Err(SafeNativeError::Abort {
abort_code: error::unavailable(EFEATURE_NOT_ENABLED),
});
}

debug_assert!(args.len() == 2);
georgemitenkov marked this conversation as resolved.
Show resolved Hide resolved

context.charge(MEM_SWAP_BASE)?;

let left = safely_pop_arg!(args, Reference);
let right = safely_pop_arg!(args, Reference);

left.swap_values(right)?;

Ok(smallvec![])
}

/***************************************************************************************************
* module
**************************************************************************************************/
pub fn make_all(
builder: &SafeNativeBuilder,
) -> impl Iterator<Item = (String, NativeFunction)> + '_ {
let natives = [("swap", native_swap as RawSafeNative)];

builder.make_named_natives(natives)
}
2 changes: 2 additions & 0 deletions aptos-move/framework/move-stdlib/src/natives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

pub mod bcs;
pub mod hash;
pub mod mem;
pub mod signer;
pub mod string;
#[cfg(feature = "testing")]
Expand All @@ -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")]
Expand Down
Loading
Loading