Skip to content

Conversation

@FrancoGiachetta
Copy link
Contributor

@FrancoGiachetta FrancoGiachetta commented Dec 2, 2025

Refactor syscalls

Closes #NA

This PR refactors syscalls' call implementation.

Key changes:

  • New helper function call_syscall which receives the expected arguments and return types and takes care of calling the syscall and creating the resulting payloads. This way, the amount of code gets drastically reduced.

  • Change the type of payload_arg in syscall send_message_to_l1. This is because it a Span<felt252>, which represents:

    struct {
        struct {
    	    ptr,
    	    start,
    	    end,
    	    capacity
        }
    }

    But it was being represented as:

    struct {
    	ptr,
    	start,
    	end,
    	capacity
    }

    Even though this was fine, since the each represent the same pointer, the former is the correct type to use.

Introduces Breaking Changes?

No.

These PRs should be merged after this one right away, in that order.

Checklist

  • Linked to Github Issue.
  • Unit tests added.
  • Integration tests added.
  • This change requires new documentation.
    • Documentation has been added/updated.

@github-actions
Copy link

github-actions bot commented Dec 2, 2025

✅ Code is now correctly formatted.

@codecov-commenter
Copy link

codecov-commenter commented Dec 2, 2025

Codecov Report

❌ Patch coverage is 31.02041% with 169 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.32%. Comparing base (53371a9) to head (a73418d).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/libfuncs/starknet.rs 31.02% 169 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1484      +/-   ##
==========================================
+ Coverage   81.47%   83.32%   +1.84%     
==========================================
  Files         105      105              
  Lines       25759    25128     -631     
==========================================
- Hits        20987    20937      -50     
+ Misses       4772     4191     -581     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link

github-actions bot commented Dec 2, 2025

Benchmark results Main vs HEAD.

Base

Command Mean [s] Min [s] Max [s] Relative
base dict_insert.cairo (JIT) 1.997 ± 0.017 1.977 2.023 1.05 ± 0.02
base dict_insert.cairo (AOT) 1.896 ± 0.023 1.859 1.928 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head dict_insert.cairo (JIT) 1.905 ± 0.023 1.883 1.957 1.05 ± 0.01
head dict_insert.cairo (AOT) 1.823 ± 0.013 1.794 1.842 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base dict_snapshot.cairo (JIT) 1.669 ± 0.012 1.643 1.685 1.06 ± 0.02
base dict_snapshot.cairo (AOT) 1.577 ± 0.024 1.546 1.619 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head dict_snapshot.cairo (JIT) 1.612 ± 0.016 1.596 1.641 1.07 ± 0.01
head dict_snapshot.cairo (AOT) 1.512 ± 0.015 1.493 1.540 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base factorial_2M.cairo (JIT) 2.054 ± 0.009 2.039 2.064 1.01 ± 0.01
base factorial_2M.cairo (AOT) 2.027 ± 0.018 1.990 2.050 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head factorial_2M.cairo (JIT) 2.000 ± 0.015 1.973 2.030 1.02 ± 0.01
head factorial_2M.cairo (AOT) 1.964 ± 0.014 1.931 1.984 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base fib_2M.cairo (JIT) 1.582 ± 0.010 1.560 1.594 1.02 ± 0.01
base fib_2M.cairo (AOT) 1.545 ± 0.014 1.518 1.561 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head fib_2M.cairo (JIT) 1.531 ± 0.012 1.514 1.548 1.03 ± 0.01
head fib_2M.cairo (AOT) 1.491 ± 0.015 1.465 1.517 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base heavy_circuit.cairo (JIT) 13.149 ± 0.093 13.016 13.287 1.04 ± 0.01
base heavy_circuit.cairo (AOT) 12.647 ± 0.057 12.577 12.751 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head heavy_circuit.cairo (JIT) 12.816 ± 0.036 12.753 12.880 1.03 ± 0.00
head heavy_circuit.cairo (AOT) 12.397 ± 0.033 12.345 12.448 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base linear_search.cairo (JIT) 1.734 ± 0.013 1.719 1.757 1.07 ± 0.02
base linear_search.cairo (AOT) 1.615 ± 0.021 1.570 1.645 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head linear_search.cairo (JIT) 1.700 ± 0.017 1.667 1.729 1.09 ± 0.02
head linear_search.cairo (AOT) 1.554 ± 0.016 1.533 1.578 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base logistic_map.cairo (JIT) 1.862 ± 0.012 1.839 1.874 1.10 ± 0.01
base logistic_map.cairo (AOT) 1.690 ± 0.015 1.661 1.713 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head logistic_map.cairo (JIT) 1.812 ± 0.015 1.790 1.837 1.09 ± 0.01
head logistic_map.cairo (AOT) 1.656 ± 0.013 1.640 1.677 1.00

@github-actions
Copy link

github-actions bot commented Dec 2, 2025

Benchmarking results

Benchmark for program dict_insert

Open benchmarks
Command Mean [s] Min [s] Max [s] Relative
Cairo-vm (Rust, Cairo 1) 11.579 ± 0.071 11.488 11.667 6.09 ± 0.06
cairo-native (embedded AOT) 1.902 ± 0.016 1.881 1.925 1.00
cairo-native (embedded JIT using LLVM's ORC Engine) 2.015 ± 0.027 1.976 2.050 1.06 ± 0.02

Benchmark for program dict_snapshot

Open benchmarks
Command Mean [ms] Min [ms] Max [ms] Relative
Cairo-vm (Rust, Cairo 1) 566.2 ± 10.7 552.6 584.1 1.00
cairo-native (embedded AOT) 1602.8 ± 25.0 1565.5 1639.7 2.83 ± 0.07
cairo-native (embedded JIT using LLVM's ORC Engine) 1723.5 ± 40.9 1692.5 1803.9 3.04 ± 0.09

Benchmark for program factorial_2M

Open benchmarks
Command Mean [s] Min [s] Max [s] Relative
Cairo-vm (Rust, Cairo 1) 5.304 ± 0.010 5.284 5.321 2.61 ± 0.03
cairo-native (embedded AOT) 2.035 ± 0.019 2.011 2.067 1.00
cairo-native (embedded JIT using LLVM's ORC Engine) 2.094 ± 0.020 2.063 2.121 1.03 ± 0.01

Benchmark for program fib_2M

Open benchmarks
Command Mean [s] Min [s] Max [s] Relative
Cairo-vm (Rust, Cairo 1) 5.163 ± 0.035 5.129 5.237 3.32 ± 0.06
cairo-native (embedded AOT) 1.557 ± 0.025 1.519 1.609 1.00
cairo-native (embedded JIT using LLVM's ORC Engine) 1.618 ± 0.023 1.581 1.653 1.04 ± 0.02

Benchmark for program heavy_circuit

Open benchmarks
Command Mean [s] Min [s] Max [s] Relative
Cairo-vm (Rust, Cairo 1) 10.032 ± 0.164 9.817 10.264 1.00
cairo-native (embedded AOT) 13.078 ± 0.135 12.902 13.311 1.30 ± 0.03
cairo-native (embedded JIT using LLVM's ORC Engine) 13.339 ± 0.074 13.238 13.470 1.33 ± 0.02

Benchmark for program linear_search

Open benchmarks
Command Mean [ms] Min [ms] Max [ms] Relative
Cairo-vm (Rust, Cairo 1) 614.2 ± 14.3 596.8 646.9 1.00
cairo-native (embedded AOT) 1623.8 ± 19.9 1595.7 1651.9 2.64 ± 0.07
cairo-native (embedded JIT using LLVM's ORC Engine) 1773.2 ± 18.1 1746.5 1796.1 2.89 ± 0.07

Benchmark for program logistic_map

Open benchmarks
Command Mean [ms] Min [ms] Max [ms] Relative
Cairo-vm (Rust, Cairo 1) 510.9 ± 6.3 499.4 518.3 1.00
cairo-native (embedded AOT) 1748.3 ± 29.9 1698.0 1810.1 3.42 ± 0.07
cairo-native (embedded JIT using LLVM's ORC Engine) 1934.5 ± 12.2 1912.4 1956.9 3.79 ± 0.05


let payload_ok = {
let value = entry.load(
let value = block.load(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be wrong, but in many of the syscalls we were moving the pointer with a .gep() operation and I think that is not being done anymore. Or is it being done in another place and I am missing it?

Copy link
Contributor Author

@FrancoGiachetta FrancoGiachetta Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An extract_value operation is similar to gep but simpler. With gep, you get to determine how much you want to offset the pointer. With extract_value you simply give the container and offset pointer based on an index. In this case, you can tell they represent the same operation because, for those syscalls using gep, they are using the result_tag_layout which is the same as indexing the ptr to the 2nd element using extract_value

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The blog post https://llvm.org/docs/Frontend/PerformanceTips.html#id6 suggests not to use extract_value on aggregate types, so it might be better to remove the extract value and use a gep instead.

Co-authored-by: DiegoC <[email protected]>
Comment on lines +2025 to +2026
/// This function receives the necessary arguments needed by the syscall as
/// well as the return types, and returns the result of its call.
Copy link
Collaborator

@gabrielbosio gabrielbosio Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about adding the corresponding arguments the docs are referencing? For instance, if I'm not mistaken:

/// This function receives the necessary arguments `args`

This would also apply to the argument/arguments referenced in return types

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't really know if this is what you meant, but I added more docs here: 0823ea5

Co-authored-by: Gabriel Bosio <[email protected]>
Comment on lines +2025 to +2026
/// This function receives the necessary arguments needed by the syscall as
/// well as the return types, and returns the result of its call.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should mention what is the expected signature of the syscall. I think not all syscalls have the same signature. Are all possible signatures supported?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also mention what are the expected arguments:

  • Is the first argument the syscall to call? If so, its better to keep it in a different argument.
  • Should the callee include the return pointer? If not, we should document it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes this function is used on syscall that don't have a type for the ok variant. We should document what to do in that case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in: 0823ea5

Comment on lines +2049 to +2064
let result_ptr = helper.init_block().alloca1(
context,
location,
llvm::r#type::r#struct(
context,
&[
result_tag_ty,
llvm::r#type::array(
IntegerType::new(context, 8).into(),
(result_layout.size() - 1).try_into()?,
),
],
false,
),
result_layout.align(),
)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why this is different from typical enum type, defined in:

pub fn build<'ctx>(

[1, 0],
[
&[remaining_gas, entry.arg(1)?, payload_err],
&[remaining_gas, entry.arg(1)?, payload_ok],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This branch has 3 values, but the signature only contains 2 values. This is not a problem because cond_br ignores the extra argument, but I would add a comment saying that payload_ok is garbage and should not used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in: 0823ea5

[1, 0],
[
&[remaining_gas, entry.arg(1)?, payload_err],
&[remaining_gas, entry.arg(1)?, payload_ok],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in: 0823ea5

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't call_syscall used here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: 0823ea5

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in: 0823ea5


let payload_ok = {
let value = entry.load(
let value = block.load(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The blog post https://llvm.org/docs/Frontend/PerformanceTips.html#id6 suggests not to use extract_value on aggregate types, so it might be better to remove the extract value and use a gep instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants