Skip to content

Commit 73d94a0

Browse files
refactor: store array data pointer inline, drop ArrayMetadata
1 parent 2463ca0 commit 73d94a0

7 files changed

Lines changed: 46 additions & 323 deletions

File tree

src/executor/contract.rs

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::{
5050
runtime::BLAKE_CALL_COUNT,
5151
starknet::{handler::StarknetSyscallHandlerCallbacks, StarknetSyscallHandler},
5252
statistics::{SierraDeclaredTypeStats, SierraFuncStats, Statistics},
53-
types::{array::ArrayMetadata, TypeBuilder},
53+
types::TypeBuilder,
5454
utils::{
5555
decode_error_message, generate_function_name, get_integer_layout, get_types_total_size,
5656
BuiltinCosts,
@@ -89,7 +89,7 @@ use std::{
8989
fs::{self, File},
9090
io,
9191
path::{Path, PathBuf},
92-
ptr::{self, NonNull},
92+
ptr::NonNull,
9393
sync::Arc,
9494
time::Instant,
9595
};
@@ -516,25 +516,7 @@ impl AotContractExecutor {
516516
};
517517
}
518518

519-
// Allocate metadata struct: { max_len: u32, data_ptr: *mut () }
520-
let metadata_ptr = if data_ptr.is_null() {
521-
ptr::null_mut()
522-
} else {
523-
unsafe {
524-
let metadata = crate::runtime::cairo_native__arena_alloc(
525-
size_of::<ArrayMetadata>() as u64,
526-
align_of::<ArrayMetadata>() as u64,
527-
)
528-
.cast::<ArrayMetadata>();
529-
metadata.write(ArrayMetadata {
530-
max_len: len_u32,
531-
data_ptr,
532-
});
533-
metadata.cast::<()>()
534-
}
535-
};
536-
537-
metadata_ptr.to_bytes(&mut invoke_data)?;
519+
data_ptr.to_bytes(&mut invoke_data)?;
538520
if cfg!(target_arch = "aarch64") {
539521
0u32.to_bytes(&mut invoke_data)?; // start
540522
len_u32.to_bytes(&mut invoke_data)?; // end
@@ -666,16 +648,13 @@ impl AotContractExecutor {
666648
let value_layout = unsafe { Layout::from_size_align_unchecked(24, 8) };
667649
let mut value_ptr = unsafe { enum_ptr.byte_add(tag_layout.extend(value_layout)?.1).cast() };
668650

669-
let metadata_ptr = unsafe { *read_value::<*mut NonNull<()>>(&mut value_ptr) };
651+
let data_ptr = unsafe { *read_value::<*mut u8>(&mut value_ptr) };
670652
let array_start = unsafe { *read_value::<u32>(&mut value_ptr) };
671653
let array_end = unsafe { *read_value::<u32>(&mut value_ptr) };
672654
let _array_capacity = unsafe { *read_value::<u32>(&mut value_ptr) };
673655

674656
let mut array_value = Vec::with_capacity((array_end - array_start) as usize);
675-
if !metadata_ptr.is_null() {
676-
let metadata = unsafe { metadata_ptr.cast::<ArrayMetadata>().read() };
677-
let data_ptr = metadata.data_ptr;
678-
657+
if !data_ptr.is_null() {
679658
let elem_stride = felt_layout.pad_to_align().size();
680659
for i in array_start..array_end {
681660
let cur_elem_ptr = unsafe { data_ptr.byte_add(elem_stride * i as usize) };

src/libfuncs/array.rs

Lines changed: 13 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ use crate::{
55
error::{Error, Result, SierraAssertError},
66
metadata::{runtime_bindings::RuntimeBindingsMeta, MetadataStorage},
77
native_assert,
8-
types::array::{
9-
calc_metadata_align, calc_metadata_size, load_data_ptr, store_data_ptr, store_max_len,
10-
},
118
utils::ProgramRegistryExt,
129
};
1310
use cairo_lang_sierra::{
@@ -189,25 +186,7 @@ pub fn build_span_from_tuple<'ctx, 'this>(
189186
// data_ptr aliases the input box: both are arena-backed.
190187
let data_ptr: Value = entry.argument(0)?.into();
191188

192-
// Allocate metadata struct from the arena.
193-
let metadata_size = entry.const_int(context, location, calc_metadata_size(), 64)?;
194-
let metadata_align_val = entry.const_int(context, location, calc_metadata_align(), 64)?;
195-
let metadata_ptr = {
196-
let rtb = metadata.get_or_insert_with(RuntimeBindingsMeta::default);
197-
rtb.arena_alloc(
198-
context,
199-
helper.module,
200-
entry,
201-
location,
202-
metadata_size,
203-
metadata_align_val,
204-
)?
205-
};
206-
207-
store_max_len(context, entry, location, metadata_ptr, array_len)?;
208-
store_data_ptr(context, entry, location, metadata_ptr, data_ptr)?;
209-
210-
// Build the array representation (4 fields: metadata_ptr, start, end, capacity)
189+
// Build the array representation (4 fields: data_ptr, start, end, capacity)
211190
let value = entry.append_op_result(llvm::undef(
212191
llvm::r#type::r#struct(context, &[ptr_ty, len_ty, len_ty, len_ty], false),
213192
location,
@@ -216,7 +195,7 @@ pub fn build_span_from_tuple<'ctx, 'this>(
216195
context,
217196
location,
218197
value,
219-
&[metadata_ptr, k0, array_len, array_len],
198+
&[data_ptr, k0, array_len, array_len],
220199
)?;
221200

222201
helper.br(entry, 0, &[value], location)
@@ -265,8 +244,7 @@ pub fn build_tuple_from_span<'ctx, 'this>(
265244
let len_ty = IntegerType::new(context, 32).into();
266245
let (_, elem_layout) = registry.build_type_with_layout(context, helper, metadata, elem_id)?;
267246

268-
let metadata_ptr =
269-
entry.extract_value(context, location, entry.argument(0)?.into(), ptr_ty, 0)?;
247+
let data_ptr = entry.extract_value(context, location, entry.argument(0)?.into(), ptr_ty, 0)?;
270248
let array_start =
271249
entry.extract_value(context, location, entry.argument(0)?.into(), len_ty, 1)?;
272250
let array_end = entry.extract_value(context, location, entry.argument(0)?.into(), len_ty, 2)?;
@@ -306,8 +284,6 @@ pub fn build_tuple_from_span<'ctx, 'this>(
306284
location,
307285
))?;
308286

309-
let data_ptr = load_data_ptr(context, valid_block, location, metadata_ptr)?;
310-
311287
let array_data_start_ptr = valid_block.gep(
312288
context,
313289
location,
@@ -376,21 +352,19 @@ pub fn build_append<'ctx, 'this>(
376352
Result::Ok((realloc_len, realloc_size))
377353
}
378354

379-
let metadata_ptr =
380-
entry.extract_value(context, location, entry.argument(0)?.into(), ptr_ty, 0)?;
355+
let data_ptr = entry.extract_value(context, location, entry.argument(0)?.into(), ptr_ty, 0)?;
381356
let null_ptr = entry.append_op_result(llvm::zero(ptr_ty, location))?;
382357
let is_empty = entry.append_op_result(
383358
ods::llvm::icmp(
384359
context,
385360
IntegerType::new(context, 1).into(),
386-
metadata_ptr,
361+
data_ptr,
387362
null_ptr,
388363
IntegerAttribute::new(IntegerType::new(context, 64).into(), 0).into(),
389364
location,
390365
)
391366
.into(),
392367
)?;
393-
let k0 = entry.const_int_from_type(context, location, 0, len_ty)?;
394368
let array_obj = entry.append_op_result(scf::r#if(
395369
is_empty,
396370
&[self_ty],
@@ -416,28 +390,8 @@ pub fn build_append<'ctx, 'this>(
416390
)?
417391
};
418392

419-
// Allocate metadata struct from the arena.
420-
let metadata_size = block.const_int(context, location, calc_metadata_size(), 64)?;
421-
let metadata_align_val =
422-
block.const_int(context, location, calc_metadata_align(), 64)?;
423-
let metadata_ptr = {
424-
let rtb = metadata.get_or_insert_with(RuntimeBindingsMeta::default);
425-
rtb.arena_alloc(
426-
context,
427-
helper.module,
428-
&block,
429-
location,
430-
metadata_size,
431-
metadata_align_val,
432-
)?
433-
};
434-
435-
store_max_len(context, &block, location, metadata_ptr, k0)?;
436-
store_data_ptr(context, &block, location, metadata_ptr, data_ptr)?;
437-
438-
// Build 4-field struct with capacity
439393
let array_obj = entry.argument(0)?.into();
440-
let array_obj = block.insert_value(context, location, array_obj, metadata_ptr, 0)?;
394+
let array_obj = block.insert_value(context, location, array_obj, data_ptr, 0)?;
441395
let array_obj = block.insert_value(context, location, array_obj, array_capacity, 3)?;
442396
block.append_operation(scf::r#yield(&[array_obj], location));
443397
region
@@ -480,22 +434,15 @@ pub fn build_append<'ctx, 'this>(
480434
array_capacity,
481435
)?;
482436

483-
let metadata_ptr = block.extract_value(
484-
context,
485-
location,
486-
entry.argument(0)?.into(),
487-
ptr_ty,
488-
0,
489-
)?;
490-
let data_ptr = load_data_ptr(context, &block, location, metadata_ptr)?;
491-
492437
// Only [0, array_end) holds live data; the tail up to capacity is unused.
493438
let array_end_64 =
494439
block.extui(array_end, IntegerType::new(context, 64).into(), location)?;
495440
let copy_size = block.muli(array_end_64, elem_stride, location)?;
496441
let data_align = block.const_int(context, location, elem_align, 64)?;
497442

498443
// Arena-realloc the data (old buffer is abandoned in the arena).
444+
// Pre-existing snapshots keep pointing at the old buffer, which remains
445+
// alive in the arena; the memcpy preserves their visible prefix.
499446
let new_data_ptr = {
500447
let rtb = metadata.get_or_insert_with(RuntimeBindingsMeta::default);
501448
rtb.arena_alloc(
@@ -509,11 +456,9 @@ pub fn build_append<'ctx, 'this>(
509456
};
510457
block.memcpy(context, location, data_ptr, new_data_ptr, copy_size);
511458

512-
// Update data_ptr in metadata
513-
store_data_ptr(context, &block, location, metadata_ptr, new_data_ptr)?;
514-
515-
// Update capacity in struct field 3
516459
let array_obj = entry.argument(0)?.into();
460+
let array_obj =
461+
block.insert_value(context, location, array_obj, new_data_ptr, 0)?;
517462
let array_obj =
518463
block.insert_value(context, location, array_obj, new_capacity, 3)?;
519464
block.append_operation(scf::r#yield(&[array_obj], location));
@@ -528,8 +473,7 @@ pub fn build_append<'ctx, 'this>(
528473
location,
529474
))?;
530475

531-
let metadata_ptr = entry.extract_value(context, location, array_obj, ptr_ty, 0)?;
532-
let data_ptr = load_data_ptr(context, entry, location, metadata_ptr)?;
476+
let data_ptr = entry.extract_value(context, location, array_obj, ptr_ty, 0)?;
533477

534478
// Insert the value.
535479
let target_offset = entry.extract_value(context, location, array_obj, len_ty, 2)?;
@@ -555,8 +499,6 @@ pub fn build_append<'ctx, 'this>(
555499
let array_end = entry.addi(array_end, k1, location)?;
556500
let array_obj = entry.insert_value(context, location, array_obj, array_end, 2)?;
557501

558-
store_max_len(context, entry, location, metadata_ptr, array_end)?;
559-
560502
helper.br(entry, 0, &[array_obj], location)
561503
}
562504

@@ -656,9 +598,7 @@ fn build_pop<'ctx, 'this, const CONSUME: bool, const REVERSE: bool>(
656598
{
657599
let mut branch_values = branch_values.clone();
658600

659-
let metadata_ptr = valid_block.extract_value(context, location, array_obj, ptr_ty, 0)?;
660-
661-
let data_ptr = load_data_ptr(context, valid_block, location, metadata_ptr)?;
601+
let data_ptr = valid_block.extract_value(context, location, array_obj, ptr_ty, 0)?;
662602

663603
let elem_stride =
664604
valid_block.const_int(context, location, elem_layout.pad_to_align().size(), 64)?;
@@ -790,9 +730,8 @@ pub fn build_get<'ctx, 'this>(
790730
)?;
791731
let source_offset = valid_block.muli(source_offset, elem_stride, location)?;
792732

793-
let metadata_ptr =
733+
let data_ptr =
794734
valid_block.extract_value(context, location, entry.argument(1)?.into(), ptr_ty, 0)?;
795-
let data_ptr = load_data_ptr(context, valid_block, location, metadata_ptr)?;
796735

797736
let source_ptr = valid_block.gep(
798737
context,

src/metadata/trace_dump.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,14 +407,12 @@ pub mod trace_dump_runtime {
407407
let mut data = Vec::with_capacity((array.until - array.since) as usize);
408408

409409
if !array.ptr.is_null() {
410-
let data_ptr = array.ptr.read();
411410
for index in (array.since)..array.until {
412411
let index = index as usize;
413-
414412
data.push(value_from_ptr(
415413
registry,
416414
&info.ty,
417-
NonNull::new(data_ptr.byte_add(layout.size() * index)).unwrap(),
415+
NonNull::new(array.ptr.byte_add(layout.size() * index)).unwrap(),
418416
));
419417
}
420418
}

src/runtime.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
use crate::{
44
starknet::{ArrayAbi, Felt252Abi},
5-
types::array::ArrayMetadata,
65
utils::{blake_utils, BuiltinCosts},
76
};
87
use bumpalo::Bump;
@@ -335,18 +334,8 @@ unsafe fn create_dict_entries_array(dict: &mut FeltDict) -> ArrayAbi<c_void> {
335334
final_value_ptr.copy_from_nonoverlapping(value, element_size);
336335
}
337336

338-
// Allocate and initialize ArrayMetadata struct from the arena
339-
let metadata_ptr = cairo_native__arena_alloc(
340-
size_of::<ArrayMetadata>() as u64,
341-
align_of::<ArrayMetadata>() as u64,
342-
) as *mut ArrayMetadata;
343-
metadata_ptr.write(ArrayMetadata {
344-
max_len: len as u32,
345-
data_ptr: data_ptr.cast::<u8>(),
346-
});
347-
348337
ArrayAbi {
349-
ptr: metadata_ptr.cast(),
338+
ptr: data_ptr.cast(),
350339
since: 0,
351340
until: len as u32,
352341
capacity: len as u32,

src/starknet.rs

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! Starknet related code for `cairo_native`
22
3-
use crate::types::array::ArrayMetadata;
43
use serde::{Deserialize, Serialize};
54
use starknet_types_core::felt::Felt;
65

@@ -9,7 +8,7 @@ pub type SyscallResult<T> = std::result::Result<T, Vec<Felt>>;
98
#[repr(C)]
109
#[derive(Debug)]
1110
pub struct ArrayAbi<T> {
12-
pub ptr: *mut *mut T,
11+
pub ptr: *mut T,
1312
pub since: u32,
1413
pub until: u32,
1514
pub capacity: u32,
@@ -24,12 +23,7 @@ impl From<&ArrayAbi<Felt252Abi>> for Vec<Felt> {
2423
let len = until_offset - since_offset;
2524
match len {
2625
0 => &[],
27-
_ => {
28-
// Access data through ArrayMetadata.data_ptr
29-
let metadata = &*value.ptr.cast::<ArrayMetadata>();
30-
let data_ptr = metadata.data_ptr.cast::<Felt252Abi>();
31-
std::slice::from_raw_parts(data_ptr.add(since_offset), len)
32-
}
26+
_ => std::slice::from_raw_parts(value.ptr.add(since_offset), len),
3327
}
3428
}
3529
.iter()
@@ -642,7 +636,7 @@ impl StarknetSyscallHandler for DummySyscallHandler {
642636
// TODO: Move to the correct place or remove if unused. See: https://github.com/starkware-libs/cairo_native/issues/1222
643637
pub(crate) mod handler {
644638
use super::*;
645-
use crate::{types::array::ArrayMetadata, utils::libc_malloc};
639+
use crate::utils::libc_malloc;
646640
use std::{
647641
alloc::Layout,
648642
fmt::Debug,
@@ -1060,7 +1054,7 @@ pub(crate) mod handler {
10601054
_ => {
10611055
let len: u32 = data.len().try_into().unwrap();
10621056

1063-
// Allocate data from the arena (no prefix).
1057+
// Allocate data from the arena.
10641058
let data_layout = Layout::array::<E>(data.len()).unwrap();
10651059
let data_ptr = crate::runtime::cairo_native__arena_alloc(
10661060
data_layout.size() as u64,
@@ -1071,18 +1065,8 @@ pub(crate) mod handler {
10711065
data_ptr.add(i).write(val.clone());
10721066
}
10731067

1074-
let metadata_layout = Layout::new::<ArrayMetadata>();
1075-
let metadata_ptr = crate::runtime::cairo_native__arena_alloc(
1076-
metadata_layout.size() as u64,
1077-
metadata_layout.align() as u64,
1078-
) as *mut ArrayMetadata;
1079-
metadata_ptr.write(ArrayMetadata {
1080-
max_len: len,
1081-
data_ptr: data_ptr.cast::<u8>(),
1082-
});
1083-
10841068
ArrayAbi {
1085-
ptr: metadata_ptr.cast(),
1069+
ptr: data_ptr,
10861070
since: 0,
10871071
until: len,
10881072
capacity: len,
@@ -1605,12 +1589,7 @@ pub(crate) mod handler {
16051589
let len = until_offset - since_offset;
16061590
match len {
16071591
0 => &[],
1608-
_ => {
1609-
// Access data through ArrayMetadata.data_ptr
1610-
let metadata = &*input.ptr.cast::<ArrayMetadata>();
1611-
let data_ptr = metadata.data_ptr.cast::<u64>();
1612-
std::slice::from_raw_parts(data_ptr.add(since_offset), len)
1613-
}
1592+
_ => std::slice::from_raw_parts(input.ptr.add(since_offset), len),
16141593
}
16151594
};
16161595

0 commit comments

Comments
 (0)