Skip to content

Commit 1381c93

Browse files
authored
Optimizing vector::replace and compiler-v2 vector depenency fix (aptos-labs#15524)
* Optimizing vector::replace with mem::replace * [compiler-v2] Also include all dependencies of vector for compiler v2 from aptos-labs#15528 --------- Co-authored-by: Igor <[email protected]>
1 parent 127df5c commit 1381c93

File tree

5 files changed

+42
-26
lines changed

5 files changed

+42
-26
lines changed

aptos-move/framework/aptos-stdlib/doc/big_vector.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ Aborts if <code>i</code> is out of bounds.
502502
<b>if</b> (self.end_index == i) {
503503
<b>return</b> last_val
504504
};
505-
// because the lack of mem::swap, here we swap remove the requested value from the bucket
505+
// because the lack of <a href="../../move-stdlib/doc/mem.md#0x1_mem_swap">mem::swap</a>, here we swap remove the requested value from the bucket
506506
// and append the last_val <b>to</b> the bucket then swap the last bucket val back
507507
<b>let</b> bucket = <a href="table_with_length.md#0x1_table_with_length_borrow_mut">table_with_length::borrow_mut</a>(&<b>mut</b> self.buckets, i / self.bucket_size);
508508
<b>let</b> bucket_len = <a href="../../move-stdlib/doc/vector.md#0x1_vector_length">vector::length</a>(bucket);

aptos-move/framework/move-stdlib/doc/vector.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ the return on investment didn't seem worth it for these simple functions.
8888
- [Function `rotate_slice`](#@Specification_1_rotate_slice)
8989

9090

91-
<pre><code></code></pre>
91+
<pre><code><b>use</b> <a href="mem.md#0x1_mem">0x1::mem</a>;
92+
</code></pre>
9293

9394

9495

@@ -930,14 +931,13 @@ Aborts if <code>i</code> is out of bounds.
930931
<pre><code><b>public</b> <b>fun</b> <a href="vector.md#0x1_vector_replace">replace</a>&lt;Element&gt;(self: &<b>mut</b> <a href="vector.md#0x1_vector">vector</a>&lt;Element&gt;, i: u64, val: Element): Element {
931932
<b>let</b> last_idx = <a href="vector.md#0x1_vector_length">length</a>(self);
932933
<b>assert</b>!(i &lt; last_idx, <a href="vector.md#0x1_vector_EINDEX_OUT_OF_BOUNDS">EINDEX_OUT_OF_BOUNDS</a>);
933-
// TODO: Enable after tests are fixed.
934-
// <b>if</b> (<a href="vector.md#0x1_vector_USE_MOVE_RANGE">USE_MOVE_RANGE</a>) {
935-
// <a href="mem.md#0x1_mem_replace">mem::replace</a>(<a href="vector.md#0x1_vector_borrow_mut">borrow_mut</a>(self, i), val)
936-
// } <b>else</b> {
937-
<a href="vector.md#0x1_vector_push_back">push_back</a>(self, val);
938-
<a href="vector.md#0x1_vector_swap">swap</a>(self, i, last_idx);
939-
<a href="vector.md#0x1_vector_pop_back">pop_back</a>(self)
940-
// }
934+
<b>if</b> (<a href="vector.md#0x1_vector_USE_MOVE_RANGE">USE_MOVE_RANGE</a>) {
935+
<a href="mem.md#0x1_mem_replace">mem::replace</a>(<a href="vector.md#0x1_vector_borrow_mut">borrow_mut</a>(self, i), val)
936+
} <b>else</b> {
937+
<a href="vector.md#0x1_vector_push_back">push_back</a>(self, val);
938+
<a href="vector.md#0x1_vector_swap">swap</a>(self, i, last_idx);
939+
<a href="vector.md#0x1_vector_pop_back">pop_back</a>(self)
940+
}
941941
}
942942
</code></pre>
943943

aptos-move/framework/move-stdlib/sources/mem.move

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
module std::mem {
33
// TODO - functions here are `public(friend)` here for one release,
44
// and to be changed to `public` one release later.
5-
// friend std::vector;
5+
friend std::vector;
66
#[test_only]
77
friend std::mem_tests;
88

aptos-move/framework/move-stdlib/sources/vector.move

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
/// Move functions here because many have loops, requiring loop invariants to prove, and
1010
/// the return on investment didn't seem worth it for these simple functions.
1111
module std::vector {
12-
// use std::mem;
12+
use std::mem;
1313

1414
/// The index into the vector is out of bounds
1515
const EINDEX_OUT_OF_BOUNDS: u64 = 0x20000;
@@ -357,14 +357,13 @@ module std::vector {
357357
public fun replace<Element>(self: &mut vector<Element>, i: u64, val: Element): Element {
358358
let last_idx = length(self);
359359
assert!(i < last_idx, EINDEX_OUT_OF_BOUNDS);
360-
// TODO: Enable after tests are fixed.
361-
// if (USE_MOVE_RANGE) {
362-
// mem::replace(borrow_mut(self, i), val)
363-
// } else {
364-
push_back(self, val);
365-
swap(self, i, last_idx);
366-
pop_back(self)
367-
// }
360+
if (USE_MOVE_RANGE) {
361+
mem::replace(borrow_mut(self, i), val)
362+
} else {
363+
push_back(self, val);
364+
swap(self, i, last_idx);
365+
pop_back(self)
366+
}
368367
}
369368

370369
/// Apply the function to each element in the vector, consuming it.

third_party/move/move-model/src/lib.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -305,13 +305,25 @@ pub fn run_model_builder_with_options_and_compilation_flags<
305305
},
306306
};
307307

308-
// Extract the module/script closure
308+
// Extract the module/script dependency closure
309309
let mut visited_modules = BTreeSet::new();
310+
// Extract the module dependency closure for the vector module
311+
let mut vector_and_its_dependencies = BTreeSet::new();
312+
let mut seen_vector = false;
310313
for (_, mident, mdef) in &expansion_ast.modules {
311314
let src_file_hash = mdef.loc.file_hash();
312315
if !dep_files.contains(&src_file_hash) {
313316
collect_related_modules_recursive(mident, &expansion_ast.modules, &mut visited_modules);
314317
}
318+
if !seen_vector && is_vector(*mident) {
319+
seen_vector = true;
320+
// Collect the vector module and its dependencies.
321+
collect_related_modules_recursive(
322+
mident,
323+
&expansion_ast.modules,
324+
&mut vector_and_its_dependencies,
325+
);
326+
}
315327
}
316328
for sdef in expansion_ast.scripts.values() {
317329
let src_file_hash = sdef.loc.file_hash();
@@ -330,14 +342,13 @@ pub fn run_model_builder_with_options_and_compilation_flags<
330342
let mut expansion_ast = {
331343
let E::Program { modules, scripts } = expansion_ast;
332344
let modules = modules.filter_map(|mident, mut mdef| {
333-
// We need to always include the `vector` module (only for compiler v2),
345+
// For compiler v2, we need to always include the `vector` module and any of its dependencies,
334346
// to handle cases of implicit usage.
335347
// E.g., index operation on a vector results in a call to `vector::borrow`.
336348
// TODO(#15483): consider refactoring code to avoid this special case.
337-
let is_vector = mident.value.address.into_addr_bytes().into_inner()
338-
== AccountAddress::ONE
339-
&& mident.value.module.0.value.as_str() == "vector";
340-
(is_vector && compile_via_model || visited_modules.contains(&mident.value)).then(|| {
349+
((compile_via_model && vector_and_its_dependencies.contains(&mident.value))
350+
|| visited_modules.contains(&mident.value))
351+
.then(|| {
341352
mdef.is_source_module = true;
342353
mdef
343354
})
@@ -416,6 +427,12 @@ pub fn run_model_builder_with_options_and_compilation_flags<
416427
}
417428
}
418429

430+
/// Is `module_ident` the `vector` module?
431+
fn is_vector(module_ident: ModuleIdent_) -> bool {
432+
module_ident.address.into_addr_bytes().into_inner() == AccountAddress::ONE
433+
&& module_ident.module.0.value.as_str() == "vector"
434+
}
435+
419436
fn run_move_checker(env: &mut GlobalEnv, program: E::Program) {
420437
let mut builder = ModelBuilder::new(env);
421438
for (module_count, (module_id, module_def)) in program

0 commit comments

Comments
 (0)