Skip to content

feat(evm): add profile-guided JIT with thread pool and sliding window profiling#481

Open
ys8888john wants to merge 5 commits into
DTVMStack:mainfrom
ys8888john:feature/profile-guided-jit
Open

feat(evm): add profile-guided JIT with thread pool and sliding window profiling#481
ys8888john wants to merge 5 commits into
DTVMStack:mainfrom
ys8888john:feature/profile-guided-jit

Conversation

@ys8888john
Copy link
Copy Markdown
Contributor

… profiling

1. Does this PR affect any open issues?(Y/N) and add issue references (e.g. "fix #123", "re #123".):

  • N
  • Y

2. What is the scope of this PR (e.g. component or file name):

3. Provide a description of the PR(e.g. more details, effects, motivations or doc link):

  • Affects user behaviors
  • Contains CI/CD configuration changes
  • Contains documentation changes
  • Contains experimental features
  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Other

4. Are there any breaking changes?(Y/N) and describe the breaking changes(e.g. more details, motivations or doc link):

  • N
  • Y

5. Are there test cases for these changes?(Y/N) select and add more details, references or doc links:

  • Unit test
  • Integration test
  • Benchmark (add benchmark stats below)
  • Manual test (add detailed scripts or steps below)
  • Other

6. Release note

None

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 22, 2026

⚡ Performance Regression Check Results

✅ Performance Check Passed (interpreter)

Performance Benchmark Results (threshold: 25%)

Benchmark Baseline (us) Current (us) Change Status
total/main/blake2b_huff/8415nulls 2.28 2.66 +16.5% PASS
total/main/blake2b_huff/empty 0.04 0.06 +71.1% PASS
total/main/blake2b_shifts/8415nulls 17.28 20.81 +20.4% PASS
total/main/sha1_divs/5311 7.57 8.70 +14.9% PASS
total/main/sha1_divs/empty 0.09 0.14 +54.0% PASS
total/main/sha1_shifts/5311 5.42 6.43 +18.6% PASS
total/main/sha1_shifts/empty 0.07 0.11 +68.0% PASS
total/main/snailtracer/benchmark 70.36 76.08 +8.1% PASS
total/main/structarray_alloc/nfts_rank 1.22 1.45 +19.2% PASS
total/main/swap_math/insufficient_liquidity 0.00 0.01 +102.9% PASS
total/main/swap_math/received 0.01 0.01 +87.7% PASS
total/main/swap_math/spent 0.01 0.01 +80.8% PASS
total/main/weierstrudel/1 0.26 0.34 +32.1% PASS
total/main/weierstrudel/15 2.69 3.29 +22.4% PASS
total/micro/JUMPDEST_n0/empty 1.88 2.91 +54.3% PASS
total/micro/jump_around/empty 0.05 0.13 +138.1% PASS
total/micro/loop_with_many_jumpdests/empty 27.93 43.61 +56.1% REGRESSED
total/micro/memory_grow_mload/by1 0.14 0.19 +39.1% PASS
total/micro/memory_grow_mload/by16 0.14 0.20 +39.2% PASS
total/micro/memory_grow_mload/by32 0.16 0.21 +32.7% PASS
total/micro/memory_grow_mload/nogrow 0.13 0.19 +40.0% PASS
total/micro/memory_grow_mstore/by1 0.14 0.19 +35.8% PASS
total/micro/memory_grow_mstore/by16 0.15 0.20 +37.5% PASS
total/micro/memory_grow_mstore/by32 0.16 0.21 +32.0% PASS
total/micro/memory_grow_mstore/nogrow 0.14 0.18 +36.0% PASS
total/micro/signextend/one 0.24 0.34 +38.0% PASS
total/micro/signextend/zero 0.24 0.34 +40.8% PASS
total/synth/ADD/b0 3.03 3.25 +7.5% PASS
total/synth/ADD/b1 3.59 3.67 +2.1% PASS
total/synth/ADDRESS/a0 5.95 4.93 -17.1% PASS
total/synth/ADDRESS/a1 6.49 5.40 -16.8% PASS
total/synth/AND/b0 2.81 3.17 +13.0% PASS
total/synth/AND/b1 3.53 3.57 +1.2% PASS
total/synth/BYTE/b0 4.76 6.25 +31.3% PASS
total/synth/BYTE/b1 4.43 5.20 +17.5% PASS
total/synth/CALLDATASIZE/a0 3.25 3.58 +10.2% PASS
total/synth/CALLDATASIZE/a1 3.31 3.42 +3.2% PASS
total/synth/CALLER/a0 5.95 4.87 -18.3% PASS
total/synth/CALLER/a1 6.46 5.37 -16.8% PASS
total/synth/CALLVALUE/a0 3.27 3.67 +12.3% PASS
total/synth/CALLVALUE/a1 3.38 3.75 +11.1% PASS
total/synth/CODESIZE/a0 3.68 4.67 +26.9% PASS
total/synth/CODESIZE/a1 3.86 4.08 +5.7% PASS
total/synth/DUP1/d0 1.61 1.45 -9.6% PASS
total/synth/DUP1/d1 1.76 1.81 +3.0% PASS
total/synth/DUP10/d0 1.61 1.45 -10.0% PASS
total/synth/DUP10/d1 1.71 1.79 +4.7% PASS
total/synth/DUP11/d0 1.61 1.45 -10.3% PASS
total/synth/DUP11/d1 1.65 1.79 +8.2% PASS
total/synth/DUP12/d0 1.61 1.45 -10.2% PASS
total/synth/DUP12/d1 1.75 1.79 +2.0% PASS
total/synth/DUP13/d0 1.62 1.45 -10.3% PASS
total/synth/DUP13/d1 1.66 1.79 +7.8% PASS
total/synth/DUP14/d0 1.62 1.45 -10.4% PASS
total/synth/DUP14/d1 1.69 1.79 +5.9% PASS
total/synth/DUP15/d0 2.45 1.45 -40.7% PASS
total/synth/DUP15/d1 1.77 1.79 +1.2% PASS
total/synth/DUP16/d0 1.62 1.45 -10.3% PASS
total/synth/DUP16/d1 1.77 1.79 +1.1% PASS
total/synth/DUP2/d0 1.61 1.45 -9.5% PASS
total/synth/DUP2/d1 1.75 1.79 +2.3% PASS
total/synth/DUP3/d0 1.61 1.45 -9.8% PASS
total/synth/DUP3/d1 1.76 1.79 +1.7% PASS
total/synth/DUP4/d0 1.61 1.45 -9.4% PASS
total/synth/DUP4/d1 1.75 1.79 +2.1% PASS
total/synth/DUP5/d0 1.61 1.45 -9.9% PASS
total/synth/DUP5/d1 1.76 1.79 +1.5% PASS
total/synth/DUP6/d0 1.61 1.45 -9.7% PASS
total/synth/DUP6/d1 1.70 1.79 +5.4% PASS
total/synth/DUP7/d0 1.61 1.45 -10.0% PASS
total/synth/DUP7/d1 1.69 1.79 +5.7% PASS
total/synth/DUP8/d0 1.61 1.22 -24.3% PASS
total/synth/DUP8/d1 1.76 1.79 +1.4% PASS
total/synth/DUP9/d0 1.61 1.45 -10.1% PASS
total/synth/DUP9/d1 1.71 1.79 +5.1% PASS
total/synth/EQ/b0 4.33 5.40 +24.8% PASS
total/synth/EQ/b1 5.10 5.65 +10.9% PASS
total/synth/GAS/a0 3.70 3.97 +7.5% PASS
total/synth/GAS/a1 3.83 4.09 +6.7% PASS
total/synth/GT/b0 4.27 5.42 +27.0% PASS
total/synth/GT/b1 5.07 5.41 +6.7% PASS
total/synth/ISZERO/u0 7.70 8.39 +8.9% PASS
total/synth/JUMPDEST/n0 1.87 2.91 +55.2% PASS
total/synth/LT/b0 4.26 5.41 +27.1% PASS
total/synth/LT/b1 5.06 5.41 +6.9% PASS
total/synth/MSIZE/a0 4.15 4.39 +5.9% PASS
total/synth/MSIZE/a1 4.61 4.91 +6.5% PASS
total/synth/MUL/b0 4.72 5.55 +17.7% PASS
total/synth/MUL/b1 5.47 5.98 +9.3% PASS
total/synth/NOT/u0 4.68 4.92 +5.1% PASS
total/synth/OR/b0 3.28 3.09 -5.9% PASS
total/synth/OR/b1 3.48 3.49 +0.5% PASS
total/synth/PC/a0 3.24 3.59 +10.8% PASS
total/synth/PC/a1 3.30 3.64 +10.4% PASS
total/synth/PUSH1/p0 1.33 1.46 +10.0% PASS
total/synth/PUSH1/p1 1.54 1.87 +21.4% PASS
total/synth/PUSH10/p0 1.33 1.46 +10.2% PASS
total/synth/PUSH10/p1 1.56 1.90 +22.0% PASS
total/synth/PUSH11/p0 1.34 1.46 +9.4% PASS
total/synth/PUSH11/p1 1.55 1.90 +22.8% PASS
total/synth/PUSH12/p0 1.34 1.46 +8.8% PASS
total/synth/PUSH12/p1 1.56 1.90 +21.9% PASS
total/synth/PUSH13/p0 1.35 1.46 +8.7% PASS
total/synth/PUSH13/p1 1.56 1.89 +21.3% PASS
total/synth/PUSH14/p0 1.32 1.48 +12.1% PASS
total/synth/PUSH14/p1 1.57 1.91 +22.1% PASS
total/synth/PUSH15/p0 1.35 1.46 +8.0% PASS
total/synth/PUSH15/p1 1.56 1.95 +24.3% PASS
total/synth/PUSH16/p0 1.34 1.44 +7.3% PASS
total/synth/PUSH16/p1 1.57 1.90 +21.2% PASS
total/synth/PUSH17/p0 1.37 1.46 +6.9% PASS
total/synth/PUSH17/p1 1.57 1.89 +20.4% PASS
total/synth/PUSH18/p0 1.34 1.46 +9.0% PASS
total/synth/PUSH18/p1 1.57 1.92 +22.5% PASS
total/synth/PUSH19/p0 1.37 1.46 +6.6% PASS
total/synth/PUSH19/p1 1.57 1.89 +20.7% PASS
total/synth/PUSH2/p0 1.32 1.46 +10.1% PASS
total/synth/PUSH2/p1 1.54 1.87 +21.2% PASS
total/synth/PUSH20/p0 1.36 1.46 +7.0% PASS
total/synth/PUSH20/p1 1.56 1.90 +22.0% PASS
total/synth/PUSH21/p0 1.36 1.46 +7.4% PASS
total/synth/PUSH21/p1 1.57 1.93 +22.6% PASS
total/synth/PUSH22/p0 1.37 1.46 +6.6% PASS
total/synth/PUSH22/p1 1.58 1.90 +20.5% PASS
total/synth/PUSH23/p0 1.38 1.46 +5.7% PASS
total/synth/PUSH23/p1 1.56 1.90 +21.5% PASS
total/synth/PUSH24/p0 1.38 1.47 +6.0% PASS
total/synth/PUSH24/p1 1.58 1.93 +22.7% PASS
total/synth/PUSH25/p0 1.36 1.46 +7.0% PASS
total/synth/PUSH25/p1 1.58 1.92 +21.6% PASS
total/synth/PUSH26/p0 1.39 1.46 +5.0% PASS
total/synth/PUSH26/p1 1.60 1.90 +18.7% PASS
total/synth/PUSH27/p0 1.37 1.46 +6.7% PASS
total/synth/PUSH27/p1 1.56 1.90 +21.6% PASS
total/synth/PUSH28/p0 1.39 1.46 +5.0% PASS
total/synth/PUSH28/p1 1.57 1.92 +22.2% PASS
total/synth/PUSH29/p0 1.37 1.46 +6.4% PASS
total/synth/PUSH29/p1 1.58 1.91 +20.7% PASS
total/synth/PUSH3/p0 1.33 1.46 +9.9% PASS
total/synth/PUSH3/p1 1.53 1.90 +24.2% PASS
total/synth/PUSH30/p0 1.35 1.52 +12.2% PASS
total/synth/PUSH30/p1 1.59 1.90 +19.5% PASS
total/synth/PUSH31/p0 1.38 1.46 +5.5% PASS
total/synth/PUSH31/p1 1.56 1.97 +26.0% PASS
total/synth/PUSH32/p0 1.37 1.46 +6.8% PASS
total/synth/PUSH32/p1 1.59 1.90 +19.8% PASS
total/synth/PUSH4/p0 1.36 1.46 +7.3% PASS
total/synth/PUSH4/p1 1.56 1.89 +21.2% PASS
total/synth/PUSH5/p0 1.33 1.46 +9.9% PASS
total/synth/PUSH5/p1 1.56 1.90 +21.9% PASS
total/synth/PUSH6/p0 1.33 1.46 +9.9% PASS
total/synth/PUSH6/p1 1.57 1.91 +22.0% PASS
total/synth/PUSH7/p0 1.33 1.46 +9.2% PASS
total/synth/PUSH7/p1 1.55 1.92 +23.7% PASS
total/synth/PUSH8/p0 1.35 1.46 +7.6% PASS
total/synth/PUSH8/p1 1.56 1.92 +23.2% PASS
total/synth/PUSH9/p0 1.34 1.46 +9.1% PASS
total/synth/PUSH9/p1 1.56 1.92 +23.3% PASS
total/synth/RETURNDATASIZE/a0 3.76 4.15 +10.2% PASS
total/synth/RETURNDATASIZE/a1 3.86 4.16 +7.9% PASS
total/synth/SAR/b0 3.89 4.08 +5.1% PASS
total/synth/SAR/b1 4.69 4.71 +0.5% PASS
total/synth/SGT/b0 3.15 4.65 +47.7% PASS
total/synth/SGT/b1 3.73 4.21 +12.7% PASS
total/synth/SHL/b0 3.81 3.68 -3.4% PASS
total/synth/SHL/b1 3.80 3.79 -0.4% PASS
total/synth/SHR/b0 3.71 3.46 -6.7% PASS
total/synth/SHR/b1 3.80 3.69 -2.8% PASS
total/synth/SIGNEXTEND/b0 3.16 3.51 +11.1% PASS
total/synth/SIGNEXTEND/b1 3.73 3.91 +4.9% PASS
total/synth/SLT/b0 3.17 4.34 +37.0% PASS
total/synth/SLT/b1 3.66 4.19 +14.4% PASS
total/synth/SUB/b0 3.02 3.47 +14.8% PASS
total/synth/SUB/b1 3.48 3.58 +2.6% PASS
total/synth/SWAP1/s0 2.13 3.37 +58.4% PASS
total/synth/SWAP10/s0 2.14 3.38 +58.1% PASS
total/synth/SWAP11/s0 2.14 3.38 +58.2% PASS
total/synth/SWAP12/s0 2.14 3.38 +58.0% PASS
total/synth/SWAP13/s0 2.14 3.38 +57.8% PASS
total/synth/SWAP14/s0 2.15 3.39 +57.4% PASS
total/synth/SWAP15/s0 2.32 3.91 +68.3% PASS
total/synth/SWAP16/s0 2.18 3.40 +56.0% PASS
total/synth/SWAP2/s0 2.13 3.37 +58.2% PASS
total/synth/SWAP3/s0 2.13 3.37 +58.5% PASS
total/synth/SWAP4/s0 2.12 3.37 +58.7% PASS
total/synth/SWAP5/s0 2.13 3.37 +58.3% PASS
total/synth/SWAP6/s0 2.14 3.38 +58.0% PASS
total/synth/SWAP7/s0 2.14 3.38 +58.0% PASS
total/synth/SWAP8/s0 2.14 3.38 +58.0% PASS
total/synth/SWAP9/s0 2.14 3.38 +58.0% PASS
total/synth/XOR/b0 2.80 3.18 +13.7% PASS
total/synth/XOR/b1 3.54 3.57 +0.8% PASS
total/synth/loop_v1 6.96 13.00 +86.7% REGRESSED
total/synth/loop_v2 7.33 13.25 +80.7% REGRESSED

Summary: 194 benchmarks, 3 regressions


✅ Performance Check Passed (multipass)

Performance Benchmark Results (threshold: 25%)

Benchmark Baseline (us) Current (us) Change Status
total/main/blake2b_huff/8415nulls 0.83 0.83 +0.3% PASS
total/main/blake2b_huff/empty 0.01 0.02 +1.6% PASS
total/main/blake2b_shifts/8415nulls 4.45 4.36 -1.9% PASS
total/main/sha1_divs/5311 0.58 0.58 +0.0% PASS
total/main/sha1_divs/empty 0.01 0.01 -0.2% PASS
total/main/sha1_shifts/5311 0.54 0.54 +0.0% PASS
total/main/sha1_shifts/empty 0.01 0.01 -0.2% PASS
total/main/snailtracer/benchmark 31.04 31.28 +0.8% PASS
total/main/structarray_alloc/nfts_rank 0.27 0.27 -0.1% PASS
total/main/swap_math/insufficient_liquidity 0.00 0.00 -0.0% PASS
total/main/swap_math/received 0.00 0.00 +0.2% PASS
total/main/swap_math/spent 0.00 0.00 -0.0% PASS
total/main/weierstrudel/1 0.24 0.25 +1.5% PASS
total/main/weierstrudel/15 2.57 2.60 +1.0% PASS
total/micro/JUMPDEST_n0/empty 0.00 0.00 -0.6% PASS
total/micro/jump_around/empty 0.06 0.06 -0.4% PASS
total/micro/loop_with_many_jumpdests/empty 0.00 0.00 +0.1% PASS
total/micro/memory_grow_mload/by1 0.01 0.01 +0.5% PASS
total/micro/memory_grow_mload/by16 0.01 0.01 +0.8% PASS
total/micro/memory_grow_mload/by32 0.01 0.01 -2.7% PASS
total/micro/memory_grow_mload/nogrow 0.01 0.01 +1.0% PASS
total/micro/memory_grow_mstore/by1 0.01 0.01 +0.3% PASS
total/micro/memory_grow_mstore/by16 0.01 0.01 +0.4% PASS
total/micro/memory_grow_mstore/by32 0.01 0.01 +1.8% PASS
total/micro/memory_grow_mstore/nogrow 0.01 0.01 -0.2% PASS
total/micro/signextend/one 0.07 0.08 +2.2% PASS
total/micro/signextend/zero 0.07 0.08 +2.0% PASS
total/synth/ADD/b0 0.00 0.00 -1.7% PASS
total/synth/ADD/b1 0.00 0.00 -1.9% PASS
total/synth/ADDRESS/a0 0.15 0.15 -0.0% PASS
total/synth/ADDRESS/a1 0.15 0.15 +0.0% PASS
total/synth/AND/b0 0.00 0.00 -1.5% PASS
total/synth/AND/b1 0.00 0.00 -1.5% PASS
total/synth/BYTE/b0 0.00 0.00 -2.0% PASS
total/synth/BYTE/b1 0.00 0.00 -1.7% PASS
total/synth/CALLDATASIZE/a0 0.07 0.07 -0.0% PASS
total/synth/CALLDATASIZE/a1 0.07 0.07 -0.1% PASS
total/synth/CALLER/a0 0.18 0.15 -14.9% PASS
total/synth/CALLER/a1 0.18 0.15 -14.7% PASS
total/synth/CALLVALUE/a0 0.19 0.19 +0.4% PASS
total/synth/CALLVALUE/a1 0.19 0.19 +0.5% PASS
total/synth/CODESIZE/a0 0.07 0.07 -0.1% PASS
total/synth/CODESIZE/a1 0.07 0.07 -0.0% PASS
total/synth/DUP1/d0 0.00 0.00 -1.4% PASS
total/synth/DUP1/d1 0.00 0.00 -1.3% PASS
total/synth/DUP10/d0 0.00 0.00 -1.6% PASS
total/synth/DUP10/d1 0.00 0.00 -1.5% PASS
total/synth/DUP11/d0 0.00 0.00 -1.5% PASS
total/synth/DUP11/d1 0.00 0.00 -1.4% PASS
total/synth/DUP12/d0 0.00 0.00 -1.5% PASS
total/synth/DUP12/d1 0.00 0.00 -1.6% PASS
total/synth/DUP13/d0 0.00 0.00 -1.8% PASS
total/synth/DUP13/d1 0.00 0.00 -1.7% PASS
total/synth/DUP14/d0 0.00 0.00 -1.6% PASS
total/synth/DUP14/d1 0.00 0.00 -2.1% PASS
total/synth/DUP15/d0 0.00 0.00 -1.1% PASS
total/synth/DUP15/d1 0.00 0.00 -1.5% PASS
total/synth/DUP16/d0 0.00 0.00 -1.6% PASS
total/synth/DUP16/d1 0.00 0.00 -1.6% PASS
total/synth/DUP2/d0 0.00 0.00 -1.2% PASS
total/synth/DUP2/d1 0.00 0.00 -1.9% PASS
total/synth/DUP3/d0 0.00 0.00 -1.6% PASS
total/synth/DUP3/d1 0.00 0.00 -1.5% PASS
total/synth/DUP4/d0 0.00 0.00 -1.9% PASS
total/synth/DUP4/d1 0.00 0.00 -1.8% PASS
total/synth/DUP5/d0 0.00 0.00 -1.1% PASS
total/synth/DUP5/d1 0.00 0.00 -1.6% PASS
total/synth/DUP6/d0 0.00 0.00 -1.7% PASS
total/synth/DUP6/d1 0.00 0.00 -2.1% PASS
total/synth/DUP7/d0 0.00 0.00 -1.8% PASS
total/synth/DUP7/d1 0.00 0.00 -1.7% PASS
total/synth/DUP8/d0 0.00 0.00 -1.5% PASS
total/synth/DUP8/d1 0.00 0.00 -1.6% PASS
total/synth/DUP9/d0 0.00 0.00 -1.6% PASS
total/synth/DUP9/d1 0.00 0.00 -1.4% PASS
total/synth/EQ/b0 0.00 0.00 -1.6% PASS
total/synth/EQ/b1 0.00 0.00 -1.5% PASS
total/synth/GAS/a0 0.76 0.76 -0.1% PASS
total/synth/GAS/a1 0.76 0.76 +0.0% PASS
total/synth/GT/b0 0.00 0.00 -1.6% PASS
total/synth/GT/b1 0.00 0.00 -1.7% PASS
total/synth/ISZERO/u0 0.00 0.00 -1.3% PASS
total/synth/JUMPDEST/n0 0.00 0.00 -1.1% PASS
total/synth/LT/b0 0.00 0.00 -1.8% PASS
total/synth/LT/b1 0.00 0.00 -1.3% PASS
total/synth/MSIZE/a0 0.00 0.00 -1.4% PASS
total/synth/MSIZE/a1 0.00 0.00 -1.7% PASS
total/synth/MUL/b0 0.00 0.00 -1.5% PASS
total/synth/MUL/b1 0.00 0.00 -1.9% PASS
total/synth/NOT/u0 0.00 0.00 -1.8% PASS
total/synth/OR/b0 0.00 0.00 -1.8% PASS
total/synth/OR/b1 0.00 0.00 -1.9% PASS
total/synth/PC/a0 0.00 0.00 -1.7% PASS
total/synth/PC/a1 0.00 0.00 -2.2% PASS
total/synth/PUSH1/p0 0.00 0.00 -1.7% PASS
total/synth/PUSH1/p1 0.00 0.00 -2.0% PASS
total/synth/PUSH10/p0 0.00 0.00 -4.3% PASS
total/synth/PUSH10/p1 0.00 0.00 -5.3% PASS
total/synth/PUSH11/p0 0.00 0.00 -1.5% PASS
total/synth/PUSH11/p1 0.00 0.00 -3.5% PASS
total/synth/PUSH12/p0 0.00 0.00 -1.6% PASS
total/synth/PUSH12/p1 0.00 0.00 -1.7% PASS
total/synth/PUSH13/p0 0.00 0.00 -1.0% PASS
total/synth/PUSH13/p1 0.00 0.00 +0.5% PASS
total/synth/PUSH14/p0 0.00 0.00 +0.7% PASS
total/synth/PUSH14/p1 0.00 0.00 +1.0% PASS
total/synth/PUSH15/p0 0.00 0.00 -2.0% PASS
total/synth/PUSH15/p1 0.00 0.00 -0.3% PASS
total/synth/PUSH16/p0 0.00 0.00 -0.9% PASS
total/synth/PUSH16/p1 0.00 0.00 -1.6% PASS
total/synth/PUSH17/p0 0.00 0.00 -2.4% PASS
total/synth/PUSH17/p1 0.00 0.00 -1.9% PASS
total/synth/PUSH18/p0 0.00 0.00 -2.0% PASS
total/synth/PUSH18/p1 0.00 0.00 -0.5% PASS
total/synth/PUSH19/p0 0.00 0.00 -1.6% PASS
total/synth/PUSH19/p1 0.00 0.00 -0.7% PASS
total/synth/PUSH2/p0 0.00 0.00 -1.3% PASS
total/synth/PUSH2/p1 0.00 0.00 -1.6% PASS
total/synth/PUSH20/p0 0.00 0.00 -1.4% PASS
total/synth/PUSH20/p1 0.00 0.00 -1.6% PASS
total/synth/PUSH21/p0 0.00 0.00 -1.3% PASS
total/synth/PUSH21/p1 0.00 0.00 -1.0% PASS
total/synth/PUSH22/p0 1.40 1.46 +4.2% PASS
total/synth/PUSH22/p1 1.62 1.88 +16.1% PASS
total/synth/PUSH23/p0 1.40 1.42 +2.1% PASS
total/synth/PUSH23/p1 1.61 1.91 +18.8% PASS
total/synth/PUSH24/p0 1.40 1.45 +3.8% PASS
total/synth/PUSH24/p1 1.62 1.93 +19.1% PASS
total/synth/PUSH25/p0 1.40 1.43 +2.5% PASS
total/synth/PUSH25/p1 1.62 1.92 +18.8% PASS
total/synth/PUSH26/p0 1.33 1.43 +7.7% PASS
total/synth/PUSH26/p1 1.61 1.92 +19.5% PASS
total/synth/PUSH27/p0 1.39 1.45 +3.7% PASS
total/synth/PUSH27/p1 1.60 1.96 +22.6% PASS
total/synth/PUSH28/p0 1.40 1.44 +3.2% PASS
total/synth/PUSH28/p1 1.60 1.88 +17.2% PASS
total/synth/PUSH29/p0 1.40 1.43 +2.2% PASS
total/synth/PUSH29/p1 1.61 1.86 +15.5% PASS
total/synth/PUSH3/p0 0.00 0.00 -1.1% PASS
total/synth/PUSH3/p1 0.00 0.00 -1.4% PASS
total/synth/PUSH30/p0 1.46 1.56 +6.5% PASS
total/synth/PUSH30/p1 1.62 1.93 +18.8% PASS
total/synth/PUSH31/p0 1.41 1.44 +2.5% PASS
total/synth/PUSH31/p1 1.70 1.99 +17.0% PASS
total/synth/PUSH32/p0 1.40 1.43 +2.4% PASS
total/synth/PUSH32/p1 1.65 1.86 +12.9% PASS
total/synth/PUSH4/p0 0.00 0.00 -2.0% PASS
total/synth/PUSH4/p1 0.00 0.00 -3.4% PASS
total/synth/PUSH5/p0 0.00 0.00 -3.5% PASS
total/synth/PUSH5/p1 0.00 0.00 -2.2% PASS
total/synth/PUSH6/p0 0.00 0.00 -0.7% PASS
total/synth/PUSH6/p1 0.00 0.00 -1.1% PASS
total/synth/PUSH7/p0 0.00 0.00 -2.4% PASS
total/synth/PUSH7/p1 0.00 0.00 -2.7% PASS
total/synth/PUSH8/p0 0.00 0.00 -2.2% PASS
total/synth/PUSH8/p1 0.00 0.00 -4.6% PASS
total/synth/PUSH9/p0 0.00 0.00 -0.7% PASS
total/synth/PUSH9/p1 0.00 0.00 -4.3% PASS
total/synth/RETURNDATASIZE/a0 0.03 0.03 -0.5% PASS
total/synth/RETURNDATASIZE/a1 0.03 0.03 -0.3% PASS
total/synth/SAR/b0 0.00 0.00 -1.3% PASS
total/synth/SAR/b1 0.00 0.00 -1.7% PASS
total/synth/SGT/b0 0.00 0.00 -1.2% PASS
total/synth/SGT/b1 0.00 0.00 -1.5% PASS
total/synth/SHL/b0 0.00 0.00 -1.5% PASS
total/synth/SHL/b1 0.00 0.00 -1.6% PASS
total/synth/SHR/b0 0.00 0.00 -1.9% PASS
total/synth/SHR/b1 0.00 0.00 -1.4% PASS
total/synth/SIGNEXTEND/b0 0.00 0.00 -1.5% PASS
total/synth/SIGNEXTEND/b1 0.00 0.00 -1.7% PASS
total/synth/SLT/b0 0.00 0.00 -1.3% PASS
total/synth/SLT/b1 0.00 0.00 -2.0% PASS
total/synth/SUB/b0 0.00 0.00 -1.6% PASS
total/synth/SUB/b1 0.00 0.00 -1.7% PASS
total/synth/SWAP1/s0 0.00 0.00 -1.7% PASS
total/synth/SWAP10/s0 0.00 0.00 -1.8% PASS
total/synth/SWAP11/s0 0.00 0.00 -2.1% PASS
total/synth/SWAP12/s0 0.00 0.00 -2.1% PASS
total/synth/SWAP13/s0 0.00 0.00 -1.8% PASS
total/synth/SWAP14/s0 0.00 0.00 -1.1% PASS
total/synth/SWAP15/s0 0.00 0.00 -1.8% PASS
total/synth/SWAP16/s0 0.00 0.00 -1.4% PASS
total/synth/SWAP2/s0 0.00 0.00 -1.7% PASS
total/synth/SWAP3/s0 0.00 0.00 -1.6% PASS
total/synth/SWAP4/s0 0.00 0.00 -1.5% PASS
total/synth/SWAP5/s0 0.00 0.00 -1.5% PASS
total/synth/SWAP6/s0 0.00 0.00 -1.7% PASS
total/synth/SWAP7/s0 0.00 0.00 -1.7% PASS
total/synth/SWAP8/s0 0.00 0.00 -1.9% PASS
total/synth/SWAP9/s0 0.00 0.00 -1.8% PASS
total/synth/XOR/b0 0.00 0.00 -1.8% PASS
total/synth/XOR/b1 0.00 0.00 -1.9% PASS
total/synth/loop_v1 1.50 1.48 -1.5% PASS
total/synth/loop_v2 1.39 1.37 -1.6% PASS

Summary: 194 benchmarks, 0 regressions


Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an optional profile-guided JIT (PGJIT) mode for EVM execution: contracts start in the interpreter, a sliding-window profiler detects “hot” contracts, and background compilation is dispatched via a small fixed thread pool. This is integrated into the EVMC VM interface and exposed via config/CLI flags.

Changes:

  • Add sliding-window profiling + background JIT compilation pool to trigger EVM JIT compilation on hot contracts.
  • Add runtime configuration + CLI/test flags for enabling PGJIT and controlling compile-thread count.
  • Make EVM JIT code publication safer for cross-thread visibility (atomic publish), and adjust eager compiler error handling/logging.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/vm/dt_evmc_vm.cpp Implements PGJIT profiling, trigger logic, and a background compile pool; integrates interpreter/JIT switching in execute().
src/runtime/config.h Adds EnableProfileGuidedJIT and NumJITCompileThreads runtime config knobs.
src/runtime/evm_module.cpp Skips eager compilation when PGJIT is enabled; waits for background compilation in destructor.
src/runtime/evm_module.h Publishes JIT code pointer atomically; stores a future for background compilation completion.
src/compiler/evm_compiler.cpp Wraps EVM JIT compilation in try/catch and publishes JIT code after mprotect.
src/runtime/runtime.cpp Chooses JIT only when JIT code is actually available; otherwise falls back to interpreter.
src/cli/dtvm.cpp Adds --enable-profile-guided-jit CLI flag.
src/tests/spec_unit_tests.cpp Adds --enable-profile-guided-jit flag to spec test runner.
src/tests/solidity_contract_tests.cpp Adds --enable-profile-guided-jit flag (but removes --enable-multipass-lazy).
src/action/compiler.cpp Always runs EVM eager compiler in multipass mode (removes lazy-flag gating for EVM).
src/compiler/evm_frontend/evm_mir_compiler.cpp Minor comment addition in MIR builder init.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/runtime/config.h
Comment on lines +42 to +48
// Enable profile-guided JIT:
// contracts start in interpreter mode; runtime profiling (sliding window
// of recent calls) determines which contracts are hot enough to trigger
// background JIT compilation. Modules are NOT compiled at load time.
bool EnableProfileGuidedJIT = false;
// Maximum number of concurrent background JIT compilation threads.
uint32_t NumJITCompileThreads = 10;
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

NumJITCompileThreads can be set to 0 programmatically, but JITCompilePool(0) will accept tasks that never run, and shutdown/destruction can then block forever waiting for unfinished futures. Add validation (e.g., in RuntimeConfig::validate) to ensure NumJITCompileThreads >= 1 (and ideally cap it consistently with set_option’s limit) when profile-guided JIT is enabled.

Copilot uses AI. Check for mistakes.
@@ -247,8 +247,9 @@ GTEST_API_ int main(int argc, char **argv) {
"Number of threads for multipass JIT(set 0 for automatic "
"determination)")
->excludes(DMMOption);
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This test binary previously exposed --enable-multipass-lazy like the other CLIs/tests, but that option is removed here. If existing CI scripts or local workflows pass --enable-multipass-lazy to this binary, they'll now fail argument parsing. Consider keeping the flag for parity/backward-compatibility (even if unused for solidity tests) alongside the new --enable-profile-guided-jit option.

Suggested change
->excludes(DMMOption);
->excludes(DMMOption);
bool EnableMultipassLazyCompatibility = false;
CLIParser.add_flag(
"--enable-multipass-lazy", EnableMultipassLazyCompatibility,
"Deprecated compatibility flag accepted for parity with other "
"multipass JIT CLIs; ignored by solidity contract tests");

Copilot uses AI. Check for mistakes.
Comment thread src/vm/dt_evmc_vm.cpp
Comment on lines 22 to +30

#include <condition_variable>
#include <cstdlib>
#include <cstring>
#include <future>
#include <mutex>
#include <optional>
#include <queue>
#include <string>
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This file now uses std::thread, std::function, and std::chrono (e.g., in JITCompilePool and updateProfileAndMaybeTriggerJIT), but the corresponding standard headers are not included here. Add the missing includes (, , ) to avoid non-portable reliance on transitive includes and potential build failures on stricter toolchains.

Suggested change
#include <condition_variable>
#include <cstdlib>
#include <cstring>
#include <future>
#include <mutex>
#include <optional>
#include <queue>
#include <string>
#include <chrono>
#include <condition_variable>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <future>
#include <mutex>
#include <optional>
#include <queue>
#include <string>
#include <thread>

Copilot uses AI. Check for mistakes.
Comment thread src/vm/dt_evmc_vm.cpp Outdated
Comment on lines +759 to +761
COMPILER::EVMAnalyzer Analyzer(Mod->getRevision());
Analyzer.analyze(reinterpret_cast<const uint8_t *>(Mod->Code), Mod->CodeSize);
if (Analyzer.getJITSuitability().ShouldFallback) {
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The JIT suitability gate here is weaker than the one used at module creation: it only checks Analyzer.getJITSuitability().ShouldFallback and ignores hasUnresolvedCompatibleDynamicReturnTrampoline(Analyzer). That can allow contracts that should be forced to interpreter mode to be JIT-compiled in profile-guided mode. Reuse the exact same predicate as EVMModule::newEVMModule() and persist the decision on the module (e.g., set Mod->ShouldFallbackToInterp=true when rejecting) so it won't keep re-evaluating/attempting JIT later.

Suggested change
COMPILER::EVMAnalyzer Analyzer(Mod->getRevision());
Analyzer.analyze(reinterpret_cast<const uint8_t *>(Mod->Code), Mod->CodeSize);
if (Analyzer.getJITSuitability().ShouldFallback) {
// Reuse the same suitability predicate as module creation and persist
// fallback on the module so we do not keep re-evaluating/re-attempting JIT.
if (Mod->ShouldFallbackToInterp) {
CurrentProfile.JITRejected = true;
return;
}
COMPILER::EVMAnalyzer Analyzer(Mod->getRevision());
Analyzer.analyze(reinterpret_cast<const uint8_t *>(Mod->Code), Mod->CodeSize);
if (Analyzer.getJITSuitability().ShouldFallback ||
hasUnresolvedCompatibleDynamicReturnTrampoline(Analyzer)) {
Mod->ShouldFallbackToInterp = true;

Copilot uses AI. Check for mistakes.
Comment thread src/vm/dt_evmc_vm.cpp
Comment on lines +894 to +921
// JIT fast path: used by both non-PGJ mode and PGJ mode after JIT is
// ready. Module and instance are already resolved above.
evmc_message MsgWithCode = *Msg;
MsgWithCode.code = reinterpret_cast<uint8_t *>(Mod->Code);
MsgWithCode.code_size = Mod->CodeSize;
TheInst->setExeResult(evmc::Result{EVMC_SUCCESS, 0, 0});
TheInst->pushMessage(&MsgWithCode);

evmc::Result Result;

#ifdef ZEN_ENABLE_VIRTUAL_STACK
if (Msg->depth == 0) {
// depth==0: set up virtual stack for stack overflow protection via guard
// pages. The virtual stack switches RSP to a separate mmap'd region.
zen::utils::VirtualStackInfo StackInfo;
StackInfo.SavedPtr1 = TheInst;
StackInfo.SavedPtr2 = &MsgWithCode;
StackInfo.SavedPtr3 = &Result;
TheInst->pushVirtualStack(&StackInfo);
StackInfo.runInVirtualStack(&callJITFromVirtualStack);
TheInst->popVirtualStack();
} else {
// depth>0: re-entered via EVMC host callback, already on physical stack
VM->RT->callEVMInJITMode(*TheInst, MsgWithCode, Result);
}
#else
VM->RT->callEVMInJITMode(*TheInst, MsgWithCode, Result);
#endif // ZEN_ENABLE_VIRTUAL_STACK
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

In non-profile-guided mode, this path unconditionally calls callEVMInJITMode(), but JIT compilation can now fail silently (EagerEVMJITCompiler::compile catches exceptions and only logs), leaving Mod->getJITCode()==nullptr. That would result in calling a null function pointer. Guard this fast path by checking Mod->getJITCode() and falling back to the interpreter (or returning an error) if JIT code is unavailable.

Copilot uses AI. Check for mistakes.
Comment on lines 107 to +114
if (RT.getConfig().Mode != common::RunMode::InterpMode) {
#ifdef ZEN_ENABLE_MULTIPASS_JIT
if (RT.getConfig().EnableProfileGuidedJIT) {
// Profile-guided JIT: skip JIT compilation at load time.
// JIT will be triggered later by the profiling logic in execute().
// Eagerly init bytecode cache for interpreter use.
(void)Mod->getBytecodeCache();
} else
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

When EnableProfileGuidedJIT is true, module creation skips the EVMAnalyzer and never sets ShouldFallbackToInterp. That means contracts that should permanently fall back to interpreter mode can still get JIT-triggered later, and the execute() hot path comment about the flag being set at creation becomes false. Consider running the analyzer even in profile-guided mode to set ShouldFallbackToInterp (without compiling), or otherwise persist the rejection decision onto the module so execute() can reliably avoid JIT for unsupported contracts.

Copilot uses AI. Check for mistakes.
@ys8888john ys8888john force-pushed the feature/profile-guided-jit branch 2 times, most recently from 09c69c1 to 8ccc5fa Compare April 30, 2026 02:35
@zoowii zoowii requested a review from Copilot May 7, 2026 03:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Comment thread src/compiler/evm_compiler.cpp Outdated
Comment on lines +108 to +113
size_t CodeSize = CodeMPool.getMemEnd() - JITCode;
platform::mprotect(JITCode, TO_MPROTECT_CODE_SIZE(CodeSize),
PROT_READ | PROT_EXEC);
// Publish JITCode only after mprotect — atomic release ensures the
// interpreter thread sees fully executable code.
EVMMod->setJITCodeAndSize(JITFuncPtr, CodeSize);
Comment thread src/vm/dt_evmc_vm.cpp Outdated
const evmc_result &Result,
EVMModule *Mod) {
std::string ModName = getStableModName(Msg);
uint64_t GasUsed = static_cast<uint64_t>(Msg->gas - Result.gas_left);
Comment thread src/vm/dt_evmc_vm.cpp Outdated
Comment on lines +89 to +99
std::string getStableModName(const evmc_message *Msg) {
static const char HexChars[] = "0123456789abcdef";
std::string Name = "mod_0x";
Name.reserve(6 + 40);
for (size_t I = 0; I < sizeof(Msg->code_address.bytes); ++I) {
uint8_t Byte = Msg->code_address.bytes[I];
Name.push_back(HexChars[Byte >> 4]);
Name.push_back(HexChars[Byte & 0x0F]);
}
return Name;
}
Comment thread src/vm/dt_evmc_vm.cpp Outdated
Comment on lines +854 to +889
// JIT not ready: run interpreter with profiling
(void)Mod->getBytecodeCache();

evmc_message MsgWithCode = *Msg;
MsgWithCode.code = reinterpret_cast<uint8_t *>(Mod->Code);
MsgWithCode.code_size = Mod->CodeSize;
TheInst->setExeResult(evmc::Result{EVMC_SUCCESS, 0, 0});
TheInst->pushMessage(&MsgWithCode);

const bool ReuseCachedInstance = !IsTransientMod && Msg->depth == 0;

std::unique_ptr<zen::evm::InterpreterExecContext> TempCtx;
zen::evm::InterpreterExecContext *CtxPtr = nullptr;
if (!ReuseCachedInstance) {
TempCtx = std::make_unique<zen::evm::InterpreterExecContext>(TheInst);
CtxPtr = TempCtx.get();
} else {
if (!VM->CachedCtx) {
VM->CachedCtx =
std::make_unique<zen::evm::InterpreterExecContext>(TheInst);
} else {
VM->CachedCtx->resetForNewCall(TheInst);
}
CtxPtr = VM->CachedCtx.get();
}

auto &Ctx = *CtxPtr;
zen::evm::BaseInterpreter Interpreter(Ctx);
Ctx.allocTopFrame(&MsgWithCode);
Interpreter.interpret();

evmc::Result Result =
std::move(const_cast<evmc::Result &>(Ctx.getExeResult()));
Result.gas_left = TheInst->getGas();

evmc_result RawResult = Result.release_raw();
Comment on lines 58 to 61
void EagerEVMJITCompiler::compile() {
auto Timer = Stats.startRecord(zen::utils::StatisticPhase::JITCompilation);
try {
auto Timer = Stats.startRecord(zen::utils::StatisticPhase::JITCompilation);

Comment thread src/vm/dt_evmc_vm.cpp Outdated
Comment on lines +851 to +856
// Profile-guided JIT: use interpreter with profiling when JIT not ready,
// then switch to JIT once compiled.
if (!Mod->getJITCode() && VM->Config.EnableProfileGuidedJIT) {
// JIT not ready: run interpreter with profiling
(void)Mod->getBytecodeCache();

ys8888john added a commit to ys8888john/DTVM that referenced this pull request May 8, 2026
@ys8888john ys8888john force-pushed the feature/profile-guided-jit branch 4 times, most recently from a1bbf4d to 69323aa Compare May 9, 2026 08:25
Comment thread src/vm/dt_evmc_vm.cpp
// - not yet evaluated (no JIT decision made), or
// - already JIT-compiled/rejected (profile data served its purpose).
if (OldProfile.WindowCallCount == 0) {
VM->ProfileStore.erase(EvictIt);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What if the evicted profile has module cache?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

nothing at all, here just rm built jit module in ProfileStore.

Comment thread src/vm/dt_evmc_vm.cpp Outdated
TaskQueue.push(
[Task = std::move(Task), Promise = std::move(Promise)]() mutable {
try {
Task();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What if taskqueue size keeps increasing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just have to wait. Do you have a better idea?

Comment thread src/runtime/evm_module.cpp Outdated
EVMModule::~EVMModule() {
#ifdef ZEN_ENABLE_JIT
if (JITCompileFuture.valid()) {
JITCompileFuture.wait();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what if compile hangs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Add a timeout check?

Copy link
Copy Markdown
Contributor

@starwarfan starwarfan left a comment

Choose a reason for hiding this comment

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

could you separate the profilestore and ringbuffer from dt_evmc_vm.cpp, the dt_evmc_vm.cpp contains too many data types

@ys8888john ys8888john force-pushed the feature/profile-guided-jit branch 2 times, most recently from aae9437 to eb9bc1f Compare May 11, 2026 06:42
@ys8888john ys8888john force-pushed the feature/profile-guided-jit branch from eb9bc1f to 0b89021 Compare May 11, 2026 07:03
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.

3 participants