@@ -48,7 +48,7 @@ use crate::{
4848 native_assert, native_panic,
4949 starknet:: { handler:: StarknetSyscallHandlerCallbacks , StarknetSyscallHandler } ,
5050 statistics:: { SierraDeclaredTypeStats , SierraFuncStats , Statistics } ,
51- types:: TypeBuilder ,
51+ types:: { array :: ArrayMetadata , TypeBuilder } ,
5252 utils:: {
5353 decode_error_message, generate_function_name, get_integer_layout, get_types_total_size,
5454 libc_free, libc_malloc, BuiltinCosts ,
@@ -482,47 +482,44 @@ impl AotContractExecutor {
482482 }
483483
484484 let felt_layout = get_integer_layout ( 252 ) . pad_to_align ( ) ;
485- let refcount_offset = crate :: types:: array:: calc_data_prefix_offset ( felt_layout) ;
486485
487486 let len_u32: u32 = args
488487 . len ( )
489488 . try_into ( )
490489 . to_native_assert_error ( "number of arguments should fit into a u32" ) ?;
491- let array_ptr = match args. len ( ) {
490+
491+ let data_ptr = match args. len ( ) {
492492 0 => std:: ptr:: null_mut ( ) ,
493- _ => unsafe {
494- let array_ptr: * mut ( ) =
495- libc_malloc ( felt_layout. size ( ) * args. len ( ) + refcount_offset) . cast ( ) ;
496-
497- // Write reference count.
498- array_ptr. cast :: < ( u32 , u32 ) > ( ) . write ( ( 1 , len_u32) ) ;
499- array_ptr. byte_add ( refcount_offset)
500- } ,
493+ _ => unsafe { libc_malloc ( felt_layout. size ( ) * args. len ( ) ) . cast :: < u8 > ( ) } ,
501494 } ;
502495
503496 for ( idx, elem) in args. iter ( ) . enumerate ( ) {
504497 let f = elem. to_bytes_le ( ) ;
505498 unsafe {
506499 std:: ptr:: copy_nonoverlapping (
507500 f. as_ptr ( ) . cast :: < u8 > ( ) ,
508- array_ptr . byte_add ( idx * felt_layout. size ( ) ) . cast :: < u8 > ( ) ,
501+ data_ptr . byte_add ( idx * felt_layout. size ( ) ) . cast :: < u8 > ( ) ,
509502 felt_layout. size ( ) ,
510503 )
511504 } ;
512505 }
513506
514- // Make double pointer.
515- let array_ptr_ptr = if array_ptr . is_null ( ) {
507+ // Allocate metadata struct: { refcount: u32, max_len: u32, data_ptr: *mut () }
508+ let metadata_ptr = if data_ptr . is_null ( ) {
516509 ptr:: null_mut ( )
517510 } else {
518511 unsafe {
519- let array_ptr_ptr = libc_malloc ( size_of :: < * mut ( ) > ( ) ) . cast :: < * mut ( ) > ( ) ;
520- array_ptr_ptr. write ( array_ptr) ;
521- array_ptr_ptr
512+ let metadata = libc_malloc ( size_of :: < ArrayMetadata > ( ) ) . cast :: < ArrayMetadata > ( ) ;
513+ metadata. write ( ArrayMetadata {
514+ refcount : 1 ,
515+ max_len : len_u32,
516+ data_ptr,
517+ } ) ;
518+ metadata. cast :: < ( ) > ( )
522519 }
523520 } ;
524521
525- array_ptr_ptr . to_bytes ( & mut invoke_data, |_| unreachable ! ( ) ) ?;
522+ metadata_ptr . to_bytes ( & mut invoke_data, |_| unreachable ! ( ) ) ?;
526523 if cfg ! ( target_arch = "aarch64" ) {
527524 0u32 . to_bytes ( & mut invoke_data, |_| unreachable ! ( ) ) ?; // start
528525 len_u32. to_bytes ( & mut invoke_data, |_| unreachable ! ( ) ) ?; // end
@@ -653,18 +650,19 @@ impl AotContractExecutor {
653650 let value_layout = unsafe { Layout :: from_size_align_unchecked ( 24 , 8 ) } ;
654651 let mut value_ptr = unsafe { enum_ptr. byte_add ( tag_layout. extend ( value_layout) ?. 1 ) . cast ( ) } ;
655652
656- let array_ptr_ptr = unsafe { * read_value :: < * mut NonNull < ( ) > > ( & mut value_ptr) } ;
653+ let metadata_ptr = unsafe { * read_value :: < * mut NonNull < ( ) > > ( & mut value_ptr) } ;
657654 let array_start = unsafe { * read_value :: < u32 > ( & mut value_ptr) } ;
658655 let array_end = unsafe { * read_value :: < u32 > ( & mut value_ptr) } ;
659656 let _array_capacity = unsafe { * read_value :: < u32 > ( & mut value_ptr) } ;
660657
661658 let mut array_value = Vec :: with_capacity ( ( array_end - array_start) as usize ) ;
662- if !array_ptr_ptr. is_null ( ) {
663- let array_ptr = unsafe { array_ptr_ptr. read ( ) } ;
659+ if !metadata_ptr. is_null ( ) {
660+ let metadata = unsafe { metadata_ptr. cast :: < ArrayMetadata > ( ) . read ( ) } ;
661+ let data_ptr = metadata. data_ptr ;
664662
665663 let elem_stride = felt_layout. pad_to_align ( ) . size ( ) ;
666664 for i in array_start..array_end {
667- let cur_elem_ptr = unsafe { array_ptr . byte_add ( elem_stride * i as usize ) } ;
665+ let cur_elem_ptr = unsafe { data_ptr . byte_add ( elem_stride * i as usize ) } ;
668666
669667 let mut data = unsafe { cur_elem_ptr. cast :: < [ u8 ; 32 ] > ( ) . read ( ) } ;
670668 data[ 31 ] &= 0x0F ; // Filter out first 4 bits (they're outside an i252).
@@ -673,13 +671,12 @@ impl AotContractExecutor {
673671 }
674672
675673 unsafe {
676- let array_ptr = array_ptr. byte_sub ( refcount_offset) ;
677674 native_assert ! (
678- array_ptr . cast :: < u32 > ( ) . read ( ) == 1 ,
675+ metadata . refcount == 1 ,
679676 "return array should have a reference count of 1"
680677 ) ;
681- libc_free ( array_ptr . as_ptr ( ) . cast ( ) ) ;
682- libc_free ( array_ptr_ptr . cast ( ) ) ;
678+ libc_free ( data_ptr . cast ( ) ) ;
679+ libc_free ( metadata_ptr . cast ( ) ) ;
683680 }
684681 }
685682
0 commit comments