@@ -182,11 +182,19 @@ void pippenger_round_parallel_batched(std::span<std::span<typename Curve::Scalar
182182 // footprint, which tracks the span. A sparse-but-wide MSM (few non-zeros, large domain) must stay
183183 // "large" — splitting by active count instead drops it into the concurrent pool and thrashes cache.
184184 const size_t pool_width = bb::get_num_cpus ();
185+ #ifdef __wasm__
186+ // wasm runs every MSM single-threaded, so the split uses a fixed point-count bound rather than
187+ // MSM_MIN_PTS_PER_THREAD (SIZE_MAX here, which would classify every member as small). The loop
188+ // below tests `n < mt_threshold` and the intended classification is `n <= SMALL_MSM_BATCH_THRESHOLD`,
189+ // so the exclusive bound is one past it.
190+ const size_t mt_threshold = SMALL_MSM_BATCH_THRESHOLD + 1 ;
191+ #else
185192 // overflow-safe MSM_MIN_PTS_PER_THREAD * pool_width
186193 const size_t mt_threshold =
187194 (pool_width <= 1 || MSM_MIN_PTS_PER_THREAD > std::numeric_limits<size_t >::max () / pool_width)
188195 ? std::numeric_limits<size_t >::max ()
189196 : MSM_MIN_PTS_PER_THREAD * pool_width;
197+ #endif
190198 std::vector<size_t > small_members;
191199 std::vector<size_t > large_members;
192200 small_members.reserve (K);
@@ -228,6 +236,11 @@ void pippenger_round_parallel_batched(std::span<std::span<typename Curve::Scalar
228236 // - max n <= Σn / pool_width (n is the work proxy): with largest-first ordering (below) the
229237 // makespan is max(largest, Σn / pool_width), so a dominant member can't strand one worker.
230238 // - pool_width >= CONCURRENT_MIN_POOL_WIDTH: fewer threads make the win too small to justify.
239+ #ifdef __wasm__
240+ // wasm keeps large members on the sequential shared-arena dispatch: with single-threaded MSMs the
241+ // concurrent path's per-worker live arenas buy nothing over one reused arena.
242+ const bool large_members_concurrent = false ;
243+ #else
231244 static constexpr size_t CONCURRENT_MIN_MEMBERS = 100 ;
232245 static constexpr size_t CONCURRENT_MIN_POOL_WIDTH = 4 ;
233246 size_t total_large_n = 0 ;
@@ -239,6 +252,7 @@ void pippenger_round_parallel_batched(std::span<std::span<typename Curve::Scalar
239252 const bool large_members_concurrent = pool_width >= CONCURRENT_MIN_POOL_WIDTH &&
240253 large_members.size () > CONCURRENT_MIN_MEMBERS &&
241254 max_large_n <= total_large_n / pool_width;
255+ #endif
242256
243257 // Shared dynamically-sized arena for the sequential (large-member) calls. Sized to
244258 // the max requirement across those members so each MSM_fast finds enough space; a
0 commit comments