Skip to content

Commit a7b3c33

Browse files
[mono-move] Aggregator natives (#20014)
Implements the sequential `0x1::aggregator_v2` natives in the MonoMove VM for both `u64` and `u128`, operating directly on the Move `Aggregator` and `AggregatorSnapshot` structs. To support one native body per concrete type, `NativeName` becomes a `Polymorphic`/`Monomorphic` enum and the specializer resolves the implementation from the call's type arguments. The differential test harness now runs only the VM(s) a step checks via `CHECK-V1`/`CHECK-V2`, letting the new test assert just the V2 result. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0214a43 commit a7b3c33

12 files changed

Lines changed: 841 additions & 100 deletions

File tree

third_party/move/mono-move/core/src/native/registry.rs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use super::context::NativeContext;
99
use crate::{
1010
interner::{InternedIdentifier, InternedModuleId},
1111
native::{NativeStatus, VMInternalError},
12+
types::InternedTypeList,
1213
};
1314
use shared_dsa::UnorderedMap;
1415
use thiserror::Error;
@@ -18,11 +19,27 @@ use thiserror::Error;
1819
#[repr(transparent)]
1920
pub struct NativeIdx(pub u32);
2021

21-
/// Fully-qualified native function name — used as keys in [`NativeRegistry`].
22-
#[derive(Clone, PartialEq, Eq, Hash)]
23-
pub struct NativeName {
24-
pub module: InternedModuleId,
25-
pub function: InternedIdentifier,
22+
/// Key under which a native is registered in a [`NativeRegistry`].
23+
///
24+
/// A native is either a template that serves every instantiation, or a body
25+
/// specialized to one concrete instantiation. The two variants let
26+
/// type-agnostic natives register once while type-sensitive natives register a
27+
/// separate body per concrete type. Resolution tries the monomorphic key first
28+
/// and falls back to the polymorphic one (see [`NativeRegistry::resolve`]).
29+
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
30+
pub enum NativeName {
31+
/// One implementation for all instantiations.
32+
Polymorphic {
33+
module: InternedModuleId,
34+
function: InternedIdentifier,
35+
},
36+
/// Implementation specialized to one concrete instantiation, matched only
37+
/// when the call's type arguments equal `ty_args`.
38+
Monomorphic {
39+
module: InternedModuleId,
40+
function: InternedIdentifier,
41+
ty_args: InternedTypeList,
42+
},
2643
}
2744

2845
/// Describes a family of [`NativeContext`] types indexed by a lifetime.
@@ -48,17 +65,28 @@ pub type NativeFunction<F> = Box<
4865
+ Sync,
4966
>;
5067

51-
/// Resolves a fully-qualified native name to its [`NativeIdx`].
68+
/// Resolves a native call to its [`NativeIdx`] from the callee's qualified name
69+
/// and the call's concrete type arguments.
5270
pub trait NativeResolver {
53-
fn resolve(&self, name: &NativeName) -> Option<NativeIdx>;
71+
fn resolve(
72+
&self,
73+
module: InternedModuleId,
74+
function: InternedIdentifier,
75+
ty_args: InternedTypeList,
76+
) -> Option<NativeIdx>;
5477
}
5578

5679
/// A [`NativeResolver`] that resolves nothing -- useful for tests and simulations that
5780
/// don't have any natives.
5881
pub struct NoNatives;
5982

6083
impl NativeResolver for NoNatives {
61-
fn resolve(&self, _name: &NativeName) -> Option<NativeIdx> {
84+
fn resolve(
85+
&self,
86+
_module: InternedModuleId,
87+
_function: InternedIdentifier,
88+
_ty_args: InternedTypeList,
89+
) -> Option<NativeIdx> {
6290
None
6391
}
6492
}
@@ -139,7 +167,19 @@ impl<F: NativeContextFamily> Default for NativeRegistry<F> {
139167
}
140168

141169
impl<F: NativeContextFamily> NativeResolver for NativeRegistry<F> {
142-
fn resolve(&self, name: &NativeName) -> Option<NativeIdx> {
143-
self.lookup_by_name(name)
170+
/// Resolves the monomorphic registration for `ty_args` if one exists,
171+
/// otherwise falls back to a polymorphic (template) registration.
172+
fn resolve(
173+
&self,
174+
module: InternedModuleId,
175+
function: InternedIdentifier,
176+
ty_args: InternedTypeList,
177+
) -> Option<NativeIdx> {
178+
self.lookup_by_name(&NativeName::Monomorphic {
179+
module,
180+
function,
181+
ty_args,
182+
})
183+
.or_else(|| self.lookup_by_name(&NativeName::Polymorphic { module, function }))
144184
}
145185
}

0 commit comments

Comments
 (0)