Skip to content

Commit

Permalink
Verbatim cherry-pick of Wolfgang's draft PR 15171 = commit #d85b919
Browse files Browse the repository at this point in the history
[move-vm] Types and opcodes for closures

This PR implements the extensions needed in the file format for representing closures:

- The type (SignatureToken) has a new variant `Function(args, result, abilities)` to represent a function type
- The opcodes are extendeed by operations `ClosPack`, `ClosPackGeneric`, and `ClosEval`

This supports bit masks for specifyinng which arguments of a function are captured when creating a closure.

Bytecode verification is extended to support the new types and opcodes. The implementation of consistency, type, and reference safety should be complete. What is missing are:

- File format serialization
- Interpreter and value representation
- Value serialization
- Connection of the new types with the various other type representations
  • Loading branch information
wrwg authored and brmataptos committed Nov 27, 2024
1 parent 3c02ba1 commit c7cd374
Show file tree
Hide file tree
Showing 39 changed files with 709 additions and 66 deletions.
4 changes: 4 additions & 0 deletions api/types/src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ pub trait Bytecode {
mutable: true,
to: Box::new(self.new_move_type(t.borrow())),
},
SignatureToken::Function(..) => {
// TODO
unimplemented!("signature token function to API MoveType")
},
}
}

Expand Down
3 changes: 3 additions & 0 deletions aptos-move/script-composer/src/decompiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ impl LocalState {
SignatureToken::Vector(s) => {
TypeTag::Vector(Box::new(Self::type_tag_from_sig_token(script, s)?))
},
SignatureToken::Function(..) => {
bail!("function types NYI for script composer")
},
SignatureToken::Struct(s) => {
let module_handle = script.module_handle_at(script.struct_handle_at(*s).module);
TypeTag::Struct(Box::new(StructTag {
Expand Down
1 change: 1 addition & 0 deletions third_party/move/move-binary-format/src/binary_views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ impl<'a> BinaryIndexedView<'a> {
Vector(ty) => AbilitySet::polymorphic_abilities(AbilitySet::VECTOR, vec![false], vec![
self.abilities(ty, constraints)?,
]),
Function(_, _, abilities) => Ok(*abilities),
Struct(idx) => {
let sh = self.struct_handle_at(*idx);
Ok(sh.abilities)
Expand Down
16 changes: 12 additions & 4 deletions third_party/move/move-binary-format/src/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ impl CompiledScriptBuilder {
sig: &SignatureToken,
) -> PartialVMResult<SignatureToken> {
use SignatureToken::*;
let import_vec =
|s: &mut Self, v: &[SignatureToken]| -> PartialVMResult<Vec<SignatureToken>> {
v.iter()
.map(|sig| s.import_signature_token(module, sig))
.collect::<PartialVMResult<Vec<_>>>()
};
Ok(match sig {
U8 => U8,
U16 => U16,
Expand All @@ -229,13 +235,15 @@ impl CompiledScriptBuilder {
MutableReference(Box::new(self.import_signature_token(module, ty)?))
},
Vector(ty) => Vector(Box::new(self.import_signature_token(module, ty)?)),
Function(args, result, abilities) => Function(
import_vec(self, args)?,
import_vec(self, result)?,
*abilities,
),
Struct(idx) => Struct(self.import_struct(module, *idx)?),
StructInstantiation(idx, inst_tys) => StructInstantiation(
self.import_struct(module, *idx)?,
inst_tys
.iter()
.map(|sig| self.import_signature_token(module, sig))
.collect::<PartialVMResult<Vec<_>>>()?,
import_vec(self, inst_tys)?,
),
})
}
Expand Down
9 changes: 5 additions & 4 deletions third_party/move/move-binary-format/src/check_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,12 +546,12 @@ impl<'a> BoundsChecker<'a> {
)?;
}
},
Call(idx) => self.check_code_unit_bounds_impl(
Call(idx) | ClosPack(idx, _) => self.check_code_unit_bounds_impl(
self.view.function_handles(),
*idx,
bytecode_offset,
)?,
CallGeneric(idx) => {
CallGeneric(idx) | ClosPackGeneric(idx, _) => {
self.check_code_unit_bounds_impl(
self.view.function_instantiations(),
*idx,
Expand Down Expand Up @@ -650,7 +650,8 @@ impl<'a> BoundsChecker<'a> {
},

// Instructions that refer to a signature
VecPack(idx, _)
ClosEval(idx)
| VecPack(idx, _)
| VecLen(idx)
| VecImmBorrow(idx)
| VecMutBorrow(idx)
Expand Down Expand Up @@ -684,7 +685,7 @@ impl<'a> BoundsChecker<'a> {
for ty in ty.preorder_traversal() {
match ty {
Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address | Signer | TypeParameter(_)
| Reference(_) | MutableReference(_) | Vector(_) => (),
| Reference(_) | MutableReference(_) | Vector(_) | Function(..) => (),
Struct(idx) => {
check_bounds_impl(self.view.struct_handles(), *idx)?;
if let Some(sh) = self.view.struct_handles().get(idx.into_index()) {
Expand Down
8 changes: 5 additions & 3 deletions third_party/move/move-binary-format/src/check_complexity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<'a> BinaryComplexityMeter<'a> {
cost = cost.saturating_add(moduel_name.len() as u64 * COST_PER_IDENT_BYTE);
},
U8 | U16 | U32 | U64 | U128 | U256 | Signer | Address | Bool | Vector(_)
| TypeParameter(_) | Reference(_) | MutableReference(_) => (),
| Function(..) | TypeParameter(_) | Reference(_) | MutableReference(_) => (),
}
}

Expand Down Expand Up @@ -262,7 +262,7 @@ impl<'a> BinaryComplexityMeter<'a> {

for instr in &code.code {
match instr {
CallGeneric(idx) => {
CallGeneric(idx) | ClosPackGeneric(idx, ..) => {
self.meter_function_instantiation(*idx)?;
},
PackGeneric(idx) | UnpackGeneric(idx) => {
Expand All @@ -284,7 +284,8 @@ impl<'a> BinaryComplexityMeter<'a> {
ImmBorrowVariantFieldGeneric(idx) | MutBorrowVariantFieldGeneric(idx) => {
self.meter_variant_field_instantiation(*idx)?;
},
VecPack(idx, _)
ClosEval(idx)
| VecPack(idx, _)
| VecLen(idx)
| VecImmBorrow(idx)
| VecMutBorrow(idx)
Expand Down Expand Up @@ -323,6 +324,7 @@ impl<'a> BinaryComplexityMeter<'a> {
| PackVariant(_)
| UnpackVariant(_)
| TestVariant(_)
| ClosPack(..)
| ReadRef
| WriteRef
| FreezeRef
Expand Down
4 changes: 4 additions & 0 deletions third_party/move/move-binary-format/src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ fn sig_to_ty(sig: &SignatureToken) -> Option<MoveTypeLayout> {
SignatureToken::U128 => Some(MoveTypeLayout::U128),
SignatureToken::U256 => Some(MoveTypeLayout::U256),
SignatureToken::Vector(v) => Some(MoveTypeLayout::Vector(Box::new(sig_to_ty(v.as_ref())?))),
SignatureToken::Function(..) => {
// TODO: do we need representation in MoveTypeLayout?
None
},
SignatureToken::Reference(_)
| SignatureToken::MutableReference(_)
| SignatureToken::Struct(_)
Expand Down
Loading

0 comments on commit c7cd374

Please sign in to comment.