Skip to content

Commit f51a00e

Browse files
update docs
1 parent 99bbaa8 commit f51a00e

File tree

1 file changed

+30
-31
lines changed

1 file changed

+30
-31
lines changed

src/metadata/libfunc_counter.rs

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
#![cfg(feature = "with-libfunc-counter")]
22
//! The libfunc counter feature is used to generate information counting how many time a libfunc has been called.
33
//!
4-
//! When this feature is used, the compiler will call three important methods:
4+
//! When this feature is used, the compiler will call one main method:
55
//!
6-
//! 1. `count_libfunc`: called before every libfunc execution.
6+
//! 1. `count_libfunc`: called before every libfunc execution. This method will handle the counting. Given a the index
7+
//! of a libfunc (relative the its declaration order), it accesses the array of counters and updates the counter.
78
//!
8-
//! 2. `build_array_counter`: called only once to build the array of counters (one for each libfuncs). The order of
9-
//! is based on the libfuncs' declaration order.
9+
//! In the context of Starknet contracts, we need to add support for building the arrays of counters for multiple executions.
10+
//! To do so, we need one important element, which must be set before every contract execution:
1011
//!
11-
//! 3. `store_array_counter`: called before finishing each entrypoint execution. It transforms the MLIR array into a
12-
//! Rust vector which is then stored in `LIBFUNC_COUNTER`, a static variable that registers the array of counters by
13-
//! execution, along with its `counter_id` (which is relative to the execution).
12+
//! * A counter to track the ID of the current array of counter, which gets updated every time we switch to another
13+
//! contract. Since a contract can call other contracts, we need a way of restoring the counter after every execution.
1414
//!
15-
//! In the context of Starknet contracts, we need to add support for building
16-
//! the arrays of counters for multiple executions. To do so, we need one important element, which must be set before every contract
17-
//! execution:
18-
//!
19-
//! A counter to track the ID of the current array of counter, which gets updated every time we switch to another
20-
//! contract. Since a contract can call other contracts, we need a way of restoring the counter after every execution.
15+
//! * An array-of-counter guard. Every time a new entrypoint is executed, a new array of counters needs to be created in order to isolate
16+
//! each of them. The guard keeps the last array that was used to restore it once the inner entrypoint execution has finished.
2117
//!
2218
//! See `cairo-native-run` for an example on how to do it.
2319
use std::collections::HashSet;
@@ -48,15 +44,15 @@ impl LibfuncCounterBinding {
4844
pub const fn symbol(self) -> &'static str {
4945
match self {
5046
LibfuncCounterBinding::CounterId => "cairo_native__counter_id",
51-
LibfuncCounterBinding::GetCounterArray => "cairo_native__get_counter_array",
47+
LibfuncCounterBinding::GetCounterArray => "cairo_native__get_counters_array",
5248
}
5349
}
5450

5551
pub const fn function_ptr(self) -> *const () {
5652
match self {
5753
LibfuncCounterBinding::CounterId => std::ptr::null(),
5854
LibfuncCounterBinding::GetCounterArray => {
59-
libfunc_counter_runtime::get_counter_array as *const ()
55+
libfunc_counter_runtime::get_counters_array as *const ()
6056
}
6157
}
6258
}
@@ -77,7 +73,7 @@ impl LibfuncCounterMeta {
7773
/// Register the global for the given binding, if not yet registered, and return
7874
/// a pointer to the stored value.
7975
///
80-
/// For the function to be available, `setup_runtime` must be called before running the module
76+
/// For the function to be available, `setup_runtime` must be called before running the module.
8177
pub fn build_function<'c, 'a>(
8278
&mut self,
8379
context: &'c Context,
@@ -151,15 +147,16 @@ impl LibfuncCounterMeta {
151147
block.append_op_result(memref::load(libfunc_counter_id_ptr, &[], location))
152148
}
153149

154-
/// Build the array of counters
155-
fn build_array_counter<'c, 'a>(
150+
/// Returns the array of counters.
151+
fn get_array_counter<'c, 'a>(
156152
&mut self,
157153
context: &'c Context,
158154
module: &Module,
159155
block: &'a Block<'c>,
160156
location: Location<'c>,
161157
) -> Result<Value<'c, 'a>> {
162158
self.build_counter_id(context, module, block, location)?;
159+
163160
let function_ptr = self.build_function(
164161
context,
165162
module,
@@ -187,7 +184,7 @@ impl LibfuncCounterMeta {
187184
let u32_ty = IntegerType::new(context, 32).into();
188185
let k1 = block.const_int(context, location, 1, 32)?;
189186

190-
let array_counter_ptr = self.build_array_counter(context, module, block, location)?;
187+
let array_counter_ptr = self.get_array_counter(context, module, block, location)?;
191188

192189
let value_counter_ptr = block.gep(
193190
context,
@@ -233,9 +230,10 @@ pub mod libfunc_counter_runtime {
233230
use crate::{
234231
error::Result,
235232
metadata::{libfunc_counter::LibfuncCounterMeta, MetadataStorage},
233+
utils::libc_malloc,
236234
};
237235

238-
/// Contains an array of vector for each execution completed
236+
/// Contains an array of vector for each execution completed.
239237
pub static LIBFUNC_COUNTER: LazyLock<Mutex<HashMap<u64, Vec<u32>>>> =
240238
LazyLock::new(|| Mutex::new(HashMap::new()));
241239

@@ -255,13 +253,13 @@ pub mod libfunc_counter_runtime {
255253
impl CountersArrayGuard {
256254
pub fn init(libfuncs_amount: usize) -> CountersArrayGuard {
257255
let u32_libfuncs_amount = libfuncs_amount * 4;
256+
let new_array: *mut u32 = unsafe { libc_malloc(u32_libfuncs_amount).cast() };
258257

259-
let new_array = unsafe { libc::malloc(u32_libfuncs_amount) as *mut u32 };
260-
258+
// All positions in the array must be initialized with 0. Since
259+
// some libfuncs declared may not be called, their respective counter
260+
// won't be updated.
261261
for i in 0..libfuncs_amount {
262-
unsafe {
263-
*(new_array.add(i)) = 0
264-
};
262+
unsafe { *(new_array.add(i)) = 0 };
265263
}
266264

267265
Self(COUNTERS_ARRAY.replace(new_array))
@@ -274,7 +272,7 @@ pub mod libfunc_counter_runtime {
274272
}
275273
}
276274

277-
/// Increase the libfunc's counter given its index
275+
/// Update the libfunc's counter based on its index, relative to the order of declaration.
278276
pub fn count_libfunc(
279277
context: &Context,
280278
module: &Module,
@@ -288,21 +286,22 @@ pub mod libfunc_counter_runtime {
288286
libfunc_counter.count_libfunc(context, module, block, location, libfunc_idx)
289287
}
290288

291-
pub extern "C" fn get_counter_array() -> *mut u32 {
289+
pub extern "C" fn get_counters_array() -> *mut u32 {
292290
COUNTERS_ARRAY.with(|x| x.get()) as *mut u32
293291
}
294292

293+
/// Converts the pointer to the counters into a Rust `Vec` and store it. Then, it frees the pointer.
294+
///
295+
/// This method should be called at the end of an entrypoint execution.
295296
pub unsafe fn store_and_free_counters_array(counter_id_ptr: *mut u64, libfuncs_amount: usize) {
296-
let counter_array_ptr = get_counter_array();
297+
let counter_array_ptr = get_counters_array();
297298
let counters_vec = slice::from_raw_parts(counter_array_ptr, libfuncs_amount).to_vec();
298299

299300
LIBFUNC_COUNTER
300301
.lock()
301302
.unwrap()
302303
.insert(*counter_id_ptr, counters_vec);
303304

304-
if !(counter_array_ptr.is_null()) {
305-
libc::free(counter_array_ptr as *mut libc::c_void);
306-
}
305+
libc::free(counter_array_ptr as *mut libc::c_void);
307306
}
308307
}

0 commit comments

Comments
 (0)