Sitelet https://github.com/starkware-libs/cairo/commit/4c88c348378da6d061f2bd9c2eb911c29821c668
Skip to content

Commit 4c88c34

Browse files
committed
bugfix(runner): Profile coupon_call like function_call (fix from_trace panic).
ProfilingInfoProcessor::from_trace detected calls by matching only CoreConcreteLibfunc::FunctionCall, but CouponCall routes through the same function_call::build and emits `call rel 0`. The coupon call's Sierra `return` then popped a stack frame the profiler never pushed, underflowing the function stack and tripping `unreachable!("End of program reached, but trace continues.")`. Match CouponCall alongside FunctionCall. Adds a profiling golden regression test exercising a coupon call.
1 parent df923bf commit 4c88c34

2 files changed

Lines changed: 66 additions & 1 deletion

File tree

‎crates/cairo-lang-runner/src/profiling.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ impl ProfilingInfo {
149149
GenStatement::Invocation(invocation) => {
150150
if matches!(
151151
builder.registry().get_libfunc(&invocation.libfunc_id),
152-
Ok(CoreConcreteLibfunc::FunctionCall(_))
152+
Ok(CoreConcreteLibfunc::FunctionCall(_) | CoreConcreteLibfunc::CouponCall(_))
153153
) {
154154
// Push to the stack.
155155
if function_stack_depth < profiling_config.max_stack_trace_depth {

‎crates/cairo-lang-runner/src/profiling_test_data/profiling‎

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,3 +324,68 @@ Weight by Sierra stack trace:
324324
test::main: 1
325325
Weight by Cairo stack trace:
326326
test::main: 1
327+
328+
//! > ==========================================================================
329+
330+
//! > Test profiling info with a coupon call (regression: profiler must frame coupon_call)
331+
332+
//! > test_runner_name
333+
test_profiling
334+
335+
//! > cairo_code
336+
use core::num::traits::WrappingAdd;
337+
338+
extern fn coupon_buy<T>() -> T nopanic;
339+
340+
fn add_with_coupon(a: u128, b: u128) -> u128 {
341+
a.wrapping_add(b)
342+
}
343+
344+
fn main() -> u128 {
345+
let coupon: add_with_coupon::Coupon = coupon_buy();
346+
add_with_coupon(3, 4, __coupon__: coupon)
347+
}
348+
349+
//! > function_name
350+
main
351+
352+
//! > expected_profiling_info
353+
Weight by sierra statement:
354+
statement 0: 3 (u128_overflowing_add([0], [1], [2]) { fallthrough([3], [4]) 5([5], [6]) })
355+
statement 1: 1 (branch_align() -> ())
356+
statement 2: 1 (store_temp<RangeCheck>([3]) -> ([3]))
357+
statement 3: 1 (store_temp<u128>([4]) -> ([4]))
358+
statement 4: 1 (return([3], [4]))
359+
statement 12: 1 (store_temp<RangeCheck>([0]) -> ([0]))
360+
statement 13: 1 (store_temp<u128>([2]) -> ([2]))
361+
statement 14: 1 (store_temp<u128>([3]) -> ([3]))
362+
statement 15: 1 (coupon_call<user@test::add_with_coupon>([0], [2], [3], [1]) -> ([4], [5]))
363+
statement 16: 1 (return([4], [5]))
364+
Weight by concrete libfunc:
365+
libfunc store_temp<u128>: 3
366+
libfunc u128_overflowing_add: 3
367+
libfunc store_temp<RangeCheck>: 2
368+
libfunc branch_align: 1
369+
libfunc coupon_call<user@test::add_with_coupon>: 1
370+
return: 2
371+
Weight by generic libfunc:
372+
libfunc store_temp: 5
373+
libfunc u128_overflowing_add: 3
374+
libfunc branch_align: 1
375+
libfunc coupon_call: 1
376+
return: 2
377+
Weight by user function (inc. generated):
378+
function test::add_with_coupon: 7
379+
function test::main: 5
380+
Weight by original user function (exc. generated):
381+
function test::add_with_coupon: 7
382+
function test::main: 5
383+
Weight by Cairo function:
384+
function core::integer::U128OverflowingAdd::overflowing_add: 7
385+
function lib.cairo::main: 5
386+
Weight by Sierra stack trace:
387+
test::main: 12
388+
test::main -> test::add_with_coupon: 7
389+
Weight by Cairo stack trace:
390+
test::main: 12
391+
test::main -> test::add_with_coupon: 7

0 commit comments

Comments
 (0)