Skip to content

Commit dd4e583

Browse files
Merge remote-tracking branch 'upstream/develop' into feat/clarity-eval-hook-tracing-improvements
2 parents e3494ad + b17d3a1 commit dd4e583

6 files changed

Lines changed: 55 additions & 19 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Shrunk `size_of::<Value>()` from 128 to 64 bytes by boxing `CallableData::trait_identifier`, halving the memory of every `Vec<Value>`, clone, and stack copy in the Clarity VM and deserializer.

clarity-types/src/tests/types/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ fn test_sequence_try_retain_utf8_keep_none() {
851851

852852
#[test]
853853
fn test_sequence_try_retain_utf8_multibyte_filter() {
854-
let dog = vec![0xF0, 0x9F, 0x90, 0xB6]; // 🐶
854+
let dog = vec![0xF0, 0x9F, 0x90, 0xB6]; // 🐶
855855
let cat = vec![0xF0, 0x9F, 0x90, 0xB1]; // 🐱
856856
let seq = SequenceData::String(CharType::UTF8(UTF8Data {
857857
data: vec![dog.clone(), cat.clone(), dog.clone()],
@@ -902,3 +902,11 @@ fn test_sequence_try_retain_internal_error() {
902902
let err = seq.try_retain::<(), _>(utils::keep_all).unwrap_err();
903903
assert!(matches!(err, RetainValuesError::Internal(_)));
904904
}
905+
906+
/// Every `Vec<Value>` in the VM scales with this size; a variant growing past
907+
/// 64 bytes doubles list memory. Box large payloads instead.
908+
#[test]
909+
fn test_value_size_regression() {
910+
// exact on 64-bit so any layout change must update this test deliberately;
911+
assert_eq!(size_of::<Value>(), 64);
912+
}

clarity-types/src/tests/types/signatures.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ fn test_type_min_size_callable_trait_matches_minimum_value_kind() {
495495
let declared_type = TypeSignature::CallableType(CallableSubtype::Trait(trait_id.clone()));
496496
let min_value = Value::CallableContract(CallableData {
497497
contract_identifier: QualifiedContractIdentifier::local("a").unwrap(),
498-
trait_identifier: Some(trait_id.clone()),
498+
trait_identifier: Some(Box::new(trait_id.clone())),
499499
});
500500
let min_value_type = TypeSignature::type_of(&min_value).unwrap();
501501

clarity-types/src/types/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ pub struct ResponseData {
244244
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
245245
pub struct CallableData {
246246
pub contract_identifier: QualifiedContractIdentifier,
247-
pub trait_identifier: Option<TraitIdentifier>,
247+
pub trait_identifier: Option<Box<TraitIdentifier>>,
248248
}
249249

250250
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]

clarity-types/src/types/signatures.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1269,7 +1269,7 @@ impl TypeSignature {
12691269
Value::Response(v) => v.type_signature()?,
12701270
Value::CallableContract(v) => {
12711271
if let Some(trait_identifier) = &v.trait_identifier {
1272-
CallableType(CallableSubtype::Trait(trait_identifier.clone()))
1272+
CallableType(CallableSubtype::Trait(trait_identifier.as_ref().clone()))
12731273
} else {
12741274
CallableType(CallableSubtype::Principal(v.contract_identifier.clone()))
12751275
}

clarity/src/vm/callables.rs

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ impl DefinedFunction {
262262
name.clone(),
263263
CallableData {
264264
contract_identifier: callee_contract_id.clone(),
265-
trait_identifier: Some(trait_identifier.clone()),
265+
trait_identifier: Some(Box::new(trait_identifier.clone())),
266266
},
267267
);
268268
}
@@ -278,7 +278,7 @@ impl DefinedFunction {
278278
name.clone(),
279279
CallableData {
280280
contract_identifier: callee_contract_id.clone(),
281-
trait_identifier: Some(trait_identifier.clone()),
281+
trait_identifier: Some(Box::new(trait_identifier.clone())),
282282
},
283283
);
284284
}
@@ -563,7 +563,7 @@ fn clarity2_implicit_cast(
563563
Value::CallableContract(callable_data),
564564
) => Value::CallableContract(CallableData {
565565
contract_identifier: callable_data.contract_identifier.clone(),
566-
trait_identifier: Some(trait_identifier.clone()),
566+
trait_identifier: Some(Box::new(trait_identifier.clone())),
567567
}),
568568
// N.B. it seems like this should be illegal, since it is converting a
569569
// principal to a callable trait, and only principal literals should be
@@ -578,7 +578,7 @@ fn clarity2_implicit_cast(
578578
Value::Principal(PrincipalData::Contract(contract_identifier)),
579579
) => Value::CallableContract(CallableData {
580580
contract_identifier: contract_identifier.clone(),
581-
trait_identifier: Some(trait_identifier.clone()),
581+
trait_identifier: Some(Box::new(trait_identifier.clone())),
582582
}),
583583
_ => value.clone(),
584584
})
@@ -621,7 +621,10 @@ mod test {
621621
let cast_contract = clarity2_implicit_cast(&trait_ty, &contract).unwrap();
622622
let cast_trait = cast_contract.expect_callable().unwrap();
623623
assert_eq!(&cast_trait.contract_identifier, &contract_identifier);
624-
assert_eq!(&cast_trait.trait_identifier.unwrap(), &trait_identifier);
624+
assert_eq!(
625+
cast_trait.trait_identifier.unwrap().as_ref(),
626+
&trait_identifier
627+
);
625628

626629
// (optional principal) -> (optional <trait>)
627630
let optional_ty = TypeSignature::new_option(trait_ty.clone()).unwrap();
@@ -633,7 +636,7 @@ mod test {
633636
trait_identifier: trait_id,
634637
}) => {
635638
assert_eq!(contract_id, &contract_identifier);
636-
assert_eq!(trait_id.as_ref().unwrap(), &trait_identifier);
639+
assert_eq!(trait_id.as_deref().unwrap(), &trait_identifier);
637640
}
638641
other => panic!("expected Value::CallableContract, got {other:?}"),
639642
}
@@ -649,7 +652,10 @@ mod test {
649652
.expect_callable()
650653
.unwrap();
651654
assert_eq!(&cast_trait.contract_identifier, &contract_identifier);
652-
assert_eq!(&cast_trait.trait_identifier.unwrap(), &trait_identifier);
655+
assert_eq!(
656+
cast_trait.trait_identifier.unwrap().as_ref(),
657+
&trait_identifier
658+
);
653659

654660
// (err principal) -> (err <trait>)
655661
let response_err_ty =
@@ -662,7 +668,10 @@ mod test {
662668
.expect_callable()
663669
.unwrap();
664670
assert_eq!(&cast_trait.contract_identifier, &contract_identifier);
665-
assert_eq!(&cast_trait.trait_identifier.unwrap(), &trait_identifier);
671+
assert_eq!(
672+
cast_trait.trait_identifier.unwrap().as_ref(),
673+
&trait_identifier
674+
);
666675

667676
// (list principal) -> (list <trait>)
668677
let list_ty = TypeSignature::list_of(trait_ty.clone(), 4).unwrap();
@@ -671,7 +680,10 @@ mod test {
671680
let items = cast_list.expect_list().unwrap();
672681
for item in items {
673682
let cast_trait = item.expect_callable().unwrap();
674-
assert_eq!(&cast_trait.trait_identifier.unwrap(), &trait_identifier);
683+
assert_eq!(
684+
cast_trait.trait_identifier.unwrap().as_ref(),
685+
&trait_identifier
686+
);
675687
}
676688

677689
// {a: principal} -> {a: <trait>}
@@ -703,7 +715,10 @@ mod test {
703715
.expect_callable()
704716
.unwrap();
705717
assert_eq!(&cast_trait.contract_identifier, &contract_identifier);
706-
assert_eq!(&cast_trait.trait_identifier.unwrap(), &trait_identifier);
718+
assert_eq!(
719+
cast_trait.trait_identifier.unwrap().as_ref(),
720+
&trait_identifier
721+
);
707722

708723
// (list (optional principal)) -> (list (optional <trait>))
709724
let list_opt_ty = TypeSignature::list_of(optional_ty.clone(), 4).unwrap();
@@ -718,7 +733,10 @@ mod test {
718733
for item in items {
719734
if let Some(cast_opt) = item.expect_optional().unwrap() {
720735
let cast_trait = cast_opt.expect_callable().unwrap();
721-
assert_eq!(&cast_trait.trait_identifier.unwrap(), &trait_identifier);
736+
assert_eq!(
737+
cast_trait.trait_identifier.unwrap().as_ref(),
738+
&trait_identifier
739+
);
722740
}
723741
}
724742

@@ -734,7 +752,10 @@ mod test {
734752
let items = cast_list.expect_list().unwrap();
735753
for item in items {
736754
let cast_trait = item.expect_result_ok().unwrap().expect_callable().unwrap();
737-
assert_eq!(&cast_trait.trait_identifier.unwrap(), &trait_identifier);
755+
assert_eq!(
756+
cast_trait.trait_identifier.unwrap().as_ref(),
757+
&trait_identifier
758+
);
738759
}
739760

740761
// (list (response uint principal)) -> (list (response uint <trait>))
@@ -749,7 +770,10 @@ mod test {
749770
let items = cast_list.expect_list().unwrap();
750771
for item in items {
751772
let cast_trait = item.expect_result_err().unwrap().expect_callable().unwrap();
752-
assert_eq!(&cast_trait.trait_identifier.unwrap(), &trait_identifier);
773+
assert_eq!(
774+
cast_trait.trait_identifier.unwrap().as_ref(),
775+
&trait_identifier
776+
);
753777
}
754778

755779
// (optional (list (response uint principal))) -> (optional (list (response uint <trait>)))
@@ -767,7 +791,10 @@ mod test {
767791
let items = inner.expect_list().unwrap();
768792
for item in items {
769793
let cast_trait = item.expect_result_err().unwrap().expect_callable().unwrap();
770-
assert_eq!(&cast_trait.trait_identifier.unwrap(), &trait_identifier);
794+
assert_eq!(
795+
cast_trait.trait_identifier.unwrap().as_ref(),
796+
&trait_identifier
797+
);
771798
}
772799

773800
// (optional (optional principal)) -> (optional (optional <trait>))
@@ -790,7 +817,7 @@ mod test {
790817
trait_identifier: trait_id,
791818
}) => {
792819
assert_eq!(contract_id, &contract_identifier);
793-
assert_eq!(trait_id.as_ref().unwrap(), &trait_identifier);
820+
assert_eq!(trait_id.as_deref().unwrap(), &trait_identifier);
794821
}
795822
other => panic!("expected Value::CallableContract, got {other:?}"),
796823
}

0 commit comments

Comments
 (0)