Stream: git-wasmtime

Topic: wasmtime / issue #12229 Code for function is too large、Hi...


view this post on Zulip Wasmtime GitHub notifications bot (Dec 29 2025 at 17:03):

crowforkotlin opened issue #12229:

Subject: "Code for function is too large" error and 1.6GB Memory Spike during JIT compilation of a 781KB Kotlin/Wasm module

Environment:

Description:
I am reporting a Compilation error: Code for function is too large that occurs during the JIT loading phase on Android.

Despite the generated .wasm binary being only 781.63 KB, the compilation fails when a single Kotlin function contains a large amount of logic/content. During the attempt to compile this module, I observed a massive RSS memory spike on the Android device, jumping from ~235 MB to over 1.6 GB in just 4 seconds, eventually resulting in the "function too large" error.

Wasmtime Configuration:
The engine is configured specifically for Android compatibility to avoid signal conflicts with ART and minimize VSS overhead:

/**
 * Creates and configures the Wasm Config object.
 *
 * Critical Android Settings:
 * 1. Signals-based traps DISABLED: To prevent conflicts with Android ART signal handlers (SIGSEGV).
 * 2. Memory Guard Size = 0: To prevent VSS (Virtual Set Size) OOM on 32-bit or limited devices.
 * 3. GC / Exceptions: Enabled for Kotlin/Wasm support.
 */
wasm_config_t *Engine::createConfig() {
    wasm_config_t *conf = wasm_config_new();

    // Feature Flags for Kotlin/Wasm support
    wasmtime_config_wasm_gc_set(conf, true);
    wasmtime_config_wasm_function_references_set(conf, true);
    wasmtime_config_wasm_exceptions_set(conf, true);

    // Optimization: Disable SIMD if not strictly needed (improves compatibility)
    wasmtime_config_wasm_simd_set(conf, false);
    wasmtime_config_wasm_relaxed_simd_set(conf, false);

    // [CRITICAL] Disable signal handlers to avoid crash conflicts with Android Runtime (ART)
    wasmtime_config_signals_based_traps_set(conf, false);

    // [CRITICAL] Set guard pages to 0 to minimize Virtual Memory usage (prevents OOM)
    wasmtime_config_memory_guard_size_set(conf, 0);

    // Set max stack size (512KB is usually sufficient for mobile logic)
    wasmtime_config_max_wasm_stack_set(conf, 512 * 1024);

    // Compiler Optimization Strategy: Optimize for Speed and Binary Size
    wasmtime_config_cranelift_opt_level_set(conf, WASMTIME_OPT_LEVEL_SPEED_AND_SIZE);
    wasmtime_config_cranelift_debug_verifier_set(conf, false);

    return conf;
}

Reproduction Steps:

  1. Add a large amount of content/logic into the wasmWasiMain function in Plugin.kt.
  2. Build the wasm file: ./gradlew wasmtime-core:plugin:compileProductionExecutableKotlinWasmWasiOptimize.
  3. The resulting plugin.wasm is ~781 KB.
  4. Load the module on an Android device using the configuration above.

Observed Behavior:

Full Android Logs:

00:49:34.204  I  [MotionEvent] ViewRootImpl windowName 'crow.wasmtime.wasmline/crow.mordecai.wasmline.MainActivity', { action=ACTION_DOWN, id[0]=0, pointerCount=1, eventTime=51746485, downTime=51746485, phoneEventTime=00:49:34.191 } moveCount:0
00:49:34.206  D  getMiuiFreeformStackInfo mTmpFrames.miuiFreeFormStackInfo: null
00:49:34.217  I  CreateGraphicsPipeline pipeline cache hit. elpased time: 0.32 ms.
00:49:34.218  E  FrameInsert open fail: No such file or directory
00:49:34.230  I  This is non sticky GC, maxfree is 33554432 minfree is 8388608
00:49:34.227  W  type=1400 audit(0.0:2008818): avc:  denied  { getopt } for  path="/dev/socket/usap_pool_primary" scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:r:zygote:s0 tclass=unix_stream_socket permissive=0 app=crow.wasmtime.wasmline
00:49:34.322  I  [MotionEvent] ViewRootImpl windowName 'crow.wasmtime.wasmline/crow.mordecai.wasmline.MainActivity', { action=ACTION_UP, id[0]=0, pointerCount=1, eventTime=51746611, downTime=51746485, phoneEventTime=00:49:34.316 } moveCount:0
00:49:34.332  I  ==============================================
00:49:34.337  I  [Android] Wasm file : plugin.wasm    ||    wasm file exits : true    ||    wasm file path :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm
00:49:34.338  I  [Android] Cwasm cache file : plugin.cwasm    ||    cache file exits : false    ||    cache file path :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.cwasm
00:49:34.345  I  [Wasmtime] Module --> Jit Compiling for /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm...
00:49:34.363  W  type=1400 audit(0.0:2008819): avc:  denied  { read } for  name="cpu.cfs_quota_us" dev="cgroup" ino=64 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008820): avc:  denied  { read } for  name="cpu.cfs_period_us" dev="cgroup" ino=65 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008821): avc:  denied  { read } for  name="cpu.cfs_quota_us" dev="cgroup" ino=10 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008822): avc:  denied  { read } for  name="cpu.cfs_period_us" dev="cgroup" ino=11 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.441  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 234952kb -> 342100kb
00:49:34.494  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 342100kb -> 428844kb
00:49:34.544  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 428844kb -> 541612kb
00:49:34.602  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 541612kb -> 657240kb
00:49:34.928  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 657240kb -> 860432kb
00:49:35.761  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 860432kb -> 959324kb
00:49:36.012  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 959324kb -> 1075892kb
00:49:36.184  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1075892kb -> 1183820kb
00:49:37.835  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1183820kb -> 1306888kb
00:49:38.482  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1306888kb -> 1450064kb
00:49:38.639  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1450064kb -> 1612484kb
00:49:38.700  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1612484kb -> 1389664kb
00:49:38.700  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1389664kb -> 1011816kb
00:49:38.702  E  [Wasmtime] Module --> Error loading module /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm: Compilation error: Code for function is too large
00:49:38.708  I  [Wasmline] Load failure, because native load return false, file path is :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm
00:49:38.790  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1011816kb -> 727648kb

Artifacts:
Wasmline-wasmline-core-plugin.wasm.zip

Analysis & Questions:

  1. Why does a relatively small Wasm file (under 1MB) trigger a "Code too large" error? It seems the Kotlin/Wasm compiler is generating a single function with extremely high complexity.
  2. The memory usage spike to 1.6GB suggests that Cranelift might be hitting a worst-case scenario in its e-graph optimization or register allocation phase.
  3. Are there any specific Cranelift settings to mitigate this, or is this a fundamental limit on function complexity regardless of the total .wasm file size?

view this post on Zulip Wasmtime GitHub notifications bot (Dec 29 2025 at 17:03):

crowforkotlin added the bug label to Issue #12229.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 29 2025 at 17:03):

crowforkotlin edited issue #12229:

Subject: "Code for function is too large" error and 1.6GB Memory Spike during JIT compilation of a 781KB Kotlin/Wasm module

Environment:

Description:
I am reporting a Compilation error: Code for function is too large that occurs during the JIT loading phase on Android.

Despite the generated .wasm binary being only 781.63 KB, the compilation fails when a single Kotlin function contains a large amount of logic/content. During the attempt to compile this module, I observed a massive RSS memory spike on the Android device, jumping from ~235 MB to over 1.6 GB in just 4 seconds, eventually resulting in the "function too large" error.

Wasmtime Configuration:
The engine is configured specifically for Android compatibility to avoid signal conflicts with ART and minimize VSS overhead:

/**
 * Creates and configures the Wasm Config object.
 *
 * Critical Android Settings:
 * 1. Signals-based traps DISABLED: To prevent conflicts with Android ART signal handlers (SIGSEGV).
 * 2. Memory Guard Size = 0: To prevent VSS (Virtual Set Size) OOM on 32-bit or limited devices.
 * 3. GC / Exceptions: Enabled for Kotlin/Wasm support.
 */
wasm_config_t *Engine::createConfig() {
    wasm_config_t *conf = wasm_config_new();

    // Feature Flags for Kotlin/Wasm support
    wasmtime_config_wasm_gc_set(conf, true);
    wasmtime_config_wasm_function_references_set(conf, true);
    wasmtime_config_wasm_exceptions_set(conf, true);

    // Optimization: Disable SIMD if not strictly needed (improves compatibility)
    wasmtime_config_wasm_simd_set(conf, false);
    wasmtime_config_wasm_relaxed_simd_set(conf, false);

    // [CRITICAL] Disable signal handlers to avoid crash conflicts with Android Runtime (ART)
    wasmtime_config_signals_based_traps_set(conf, false);

    // [CRITICAL] Set guard pages to 0 to minimize Virtual Memory usage (prevents OOM)
    wasmtime_config_memory_guard_size_set(conf, 0);

    // Set max stack size (512KB is usually sufficient for mobile logic)
    wasmtime_config_max_wasm_stack_set(conf, 512 * 1024);

    // Compiler Optimization Strategy: Optimize for Speed and Binary Size
    wasmtime_config_cranelift_opt_level_set(conf, WASMTIME_OPT_LEVEL_SPEED_AND_SIZE);
    wasmtime_config_cranelift_debug_verifier_set(conf, false);

    return conf;
}

Reproduction Steps:

  1. Add a large amount of content/logic into the wasmWasiMain function in Plugin.kt.
  2. Build the wasm file: ./gradlew wasmtime-core:plugin:compileProductionExecutableKotlinWasmWasiOptimize.
  3. The resulting plugin.wasm is ~781 KB.
  4. Load the module on an Android device using the configuration above.

Observed Behavior:

Full Android Logs:

00:49:34.204  I  [MotionEvent] ViewRootImpl windowName 'crow.wasmtime.wasmline/crow.mordecai.wasmline.MainActivity', { action=ACTION_DOWN, id[0]=0, pointerCount=1, eventTime=51746485, downTime=51746485, phoneEventTime=00:49:34.191 } moveCount:0
00:49:34.206  D  getMiuiFreeformStackInfo mTmpFrames.miuiFreeFormStackInfo: null
00:49:34.217  I  CreateGraphicsPipeline pipeline cache hit. elpased time: 0.32 ms.
00:49:34.218  E  FrameInsert open fail: No such file or directory
00:49:34.230  I  This is non sticky GC, maxfree is 33554432 minfree is 8388608
00:49:34.227  W  type=1400 audit(0.0:2008818): avc:  denied  { getopt } for  path="/dev/socket/usap_pool_primary" scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:r:zygote:s0 tclass=unix_stream_socket permissive=0 app=crow.wasmtime.wasmline
00:49:34.322  I  [MotionEvent] ViewRootImpl windowName 'crow.wasmtime.wasmline/crow.mordecai.wasmline.MainActivity', { action=ACTION_UP, id[0]=0, pointerCount=1, eventTime=51746611, downTime=51746485, phoneEventTime=00:49:34.316 } moveCount:0
00:49:34.332  I  ==============================================
00:49:34.337  I  [Android] Wasm file : plugin.wasm    ||    wasm file exits : true    ||    wasm file path :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm
00:49:34.338  I  [Android] Cwasm cache file : plugin.cwasm    ||    cache file exits : false    ||    cache file path :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.cwasm
00:49:34.345  I  [Wasmtime] Module --> Jit Compiling for /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm...
00:49:34.363  W  type=1400 audit(0.0:2008819): avc:  denied  { read } for  name="cpu.cfs_quota_us" dev="cgroup" ino=64 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008820): avc:  denied  { read } for  name="cpu.cfs_period_us" dev="cgroup" ino=65 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008821): avc:  denied  { read } for  name="cpu.cfs_quota_us" dev="cgroup" ino=10 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008822): avc:  denied  { read } for  name="cpu.cfs_period_us" dev="cgroup" ino=11 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.441  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 234952kb -> 342100kb
00:49:34.494  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 342100kb -> 428844kb
00:49:34.544  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 428844kb -> 541612kb
00:49:34.602  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 541612kb -> 657240kb
00:49:34.928  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 657240kb -> 860432kb
00:49:35.761  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 860432kb -> 959324kb
00:49:36.012  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 959324kb -> 1075892kb
00:49:36.184  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1075892kb -> 1183820kb
00:49:37.835  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1183820kb -> 1306888kb
00:49:38.482  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1306888kb -> 1450064kb
00:49:38.639  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1450064kb -> 1612484kb
00:49:38.700  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1612484kb -> 1389664kb
00:49:38.700  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1389664kb -> 1011816kb
00:49:38.702  E  [Wasmtime] Module --> Error loading module /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm: Compilation error: Code for function is too large
00:49:38.708  I  [Wasmline] Load failure, because native load return false, file path is :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm
00:49:38.790  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1011816kb -> 727648kb

Artifacts:
Wasmline-wasmline-core-plugin.wasm.zip

Analysis & Questions:

  1. Why does a relatively small Wasm file (under 1MB) trigger a "Code too large" error? It seems the Kotlin/Wasm compiler is generating a single function with extremely high complexity.
  2. The memory usage spike to 1.6GB suggests that Cranelift might be hitting a worst-case scenario in its e-graph optimization or register allocation phase.
  3. Are there any specific Cranelift settings to mitigate this, or is this a fundamental limit on function complexity regardless of the total .wasm file size?

view this post on Zulip Wasmtime GitHub notifications bot (Dec 29 2025 at 17:04):

crowforkotlin commented on issue #12229:

#11682 @cfallin

view this post on Zulip Wasmtime GitHub notifications bot (Dec 29 2025 at 17:04):

crowforkotlin edited issue #12229:

"Code for function is too large" error and 1.6GB Memory Spike during JIT compilation of a 781KB Kotlin/Wasm module

Environment:

Description:
I am reporting a Compilation error: Code for function is too large that occurs during the JIT loading phase on Android.

Despite the generated .wasm binary being only 781.63 KB, the compilation fails when a single Kotlin function contains a large amount of logic/content. During the attempt to compile this module, I observed a massive RSS memory spike on the Android device, jumping from ~235 MB to over 1.6 GB in just 4 seconds, eventually resulting in the "function too large" error.

Wasmtime Configuration:
The engine is configured specifically for Android compatibility to avoid signal conflicts with ART and minimize VSS overhead:

/**
 * Creates and configures the Wasm Config object.
 *
 * Critical Android Settings:
 * 1. Signals-based traps DISABLED: To prevent conflicts with Android ART signal handlers (SIGSEGV).
 * 2. Memory Guard Size = 0: To prevent VSS (Virtual Set Size) OOM on 32-bit or limited devices.
 * 3. GC / Exceptions: Enabled for Kotlin/Wasm support.
 */
wasm_config_t *Engine::createConfig() {
    wasm_config_t *conf = wasm_config_new();

    // Feature Flags for Kotlin/Wasm support
    wasmtime_config_wasm_gc_set(conf, true);
    wasmtime_config_wasm_function_references_set(conf, true);
    wasmtime_config_wasm_exceptions_set(conf, true);

    // Optimization: Disable SIMD if not strictly needed (improves compatibility)
    wasmtime_config_wasm_simd_set(conf, false);
    wasmtime_config_wasm_relaxed_simd_set(conf, false);

    // [CRITICAL] Disable signal handlers to avoid crash conflicts with Android Runtime (ART)
    wasmtime_config_signals_based_traps_set(conf, false);

    // [CRITICAL] Set guard pages to 0 to minimize Virtual Memory usage (prevents OOM)
    wasmtime_config_memory_guard_size_set(conf, 0);

    // Set max stack size (512KB is usually sufficient for mobile logic)
    wasmtime_config_max_wasm_stack_set(conf, 512 * 1024);

    // Compiler Optimization Strategy: Optimize for Speed and Binary Size
    wasmtime_config_cranelift_opt_level_set(conf, WASMTIME_OPT_LEVEL_SPEED_AND_SIZE);
    wasmtime_config_cranelift_debug_verifier_set(conf, false);

    return conf;
}

Reproduction Steps:

  1. Add a large amount of content/logic into the wasmWasiMain function in Plugin.kt.
  2. Build the wasm file: ./gradlew wasmtime-core:plugin:compileProductionExecutableKotlinWasmWasiOptimize.
  3. The resulting plugin.wasm is ~781 KB.
  4. Load the module on an Android device using the configuration above.

Observed Behavior:

Full Android Logs:

00:49:34.204  I  [MotionEvent] ViewRootImpl windowName 'crow.wasmtime.wasmline/crow.mordecai.wasmline.MainActivity', { action=ACTION_DOWN, id[0]=0, pointerCount=1, eventTime=51746485, downTime=51746485, phoneEventTime=00:49:34.191 } moveCount:0
00:49:34.206  D  getMiuiFreeformStackInfo mTmpFrames.miuiFreeFormStackInfo: null
00:49:34.217  I  CreateGraphicsPipeline pipeline cache hit. elpased time: 0.32 ms.
00:49:34.218  E  FrameInsert open fail: No such file or directory
00:49:34.230  I  This is non sticky GC, maxfree is 33554432 minfree is 8388608
00:49:34.227  W  type=1400 audit(0.0:2008818): avc:  denied  { getopt } for  path="/dev/socket/usap_pool_primary" scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:r:zygote:s0 tclass=unix_stream_socket permissive=0 app=crow.wasmtime.wasmline
00:49:34.322  I  [MotionEvent] ViewRootImpl windowName 'crow.wasmtime.wasmline/crow.mordecai.wasmline.MainActivity', { action=ACTION_UP, id[0]=0, pointerCount=1, eventTime=51746611, downTime=51746485, phoneEventTime=00:49:34.316 } moveCount:0
00:49:34.332  I  ==============================================
00:49:34.337  I  [Android] Wasm file : plugin.wasm    ||    wasm file exits : true    ||    wasm file path :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm
00:49:34.338  I  [Android] Cwasm cache file : plugin.cwasm    ||    cache file exits : false    ||    cache file path :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.cwasm
00:49:34.345  I  [Wasmtime] Module --> Jit Compiling for /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm...
00:49:34.363  W  type=1400 audit(0.0:2008819): avc:  denied  { read } for  name="cpu.cfs_quota_us" dev="cgroup" ino=64 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008820): avc:  denied  { read } for  name="cpu.cfs_period_us" dev="cgroup" ino=65 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008821): avc:  denied  { read } for  name="cpu.cfs_quota_us" dev="cgroup" ino=10 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008822): avc:  denied  { read } for  name="cpu.cfs_period_us" dev="cgroup" ino=11 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.441  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 234952kb -> 342100kb
00:49:34.494  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 342100kb -> 428844kb
00:49:34.544  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 428844kb -> 541612kb
00:49:34.602  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 541612kb -> 657240kb
00:49:34.928  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 657240kb -> 860432kb
00:49:35.761  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 860432kb -> 959324kb
00:49:36.012  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 959324kb -> 1075892kb
00:49:36.184  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1075892kb -> 1183820kb
00:49:37.835  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1183820kb -> 1306888kb
00:49:38.482  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1306888kb -> 1450064kb
00:49:38.639  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1450064kb -> 1612484kb
00:49:38.700  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1612484kb -> 1389664kb
00:49:38.700  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1389664kb -> 1011816kb
00:49:38.702  E  [Wasmtime] Module --> Error loading module /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm: Compilation error: Code for function is too large
00:49:38.708  I  [Wasmline] Load failure, because native load return false, file path is :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm
00:49:38.790  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1011816kb -> 727648kb

Artifacts:
Wasmline-wasmline-core-plugin.wasm.zip

Analysis & Questions:

  1. Why does a relatively small Wasm file (under 1MB) trigger a "Code too large" error? It seems the Kotlin/Wasm compiler is generating a single function with extremely high complexity.
  2. The memory usage spike to 1.6GB suggests that Cranelift might be hitting a worst-case scenario in its e-graph optimization or register allocation phase.
  3. Are there any specific Cranelift settings to mitigate this, or is this a fundamental limit on function complexity regardless of the total .wasm file size?

view this post on Zulip Wasmtime GitHub notifications bot (Dec 29 2025 at 17:10):

crowforkotlin commented on issue #12229:

<img width="1739" height="467" alt="Image" src="https://github.com/user-attachments/assets/54509e4b-a92b-4792-a6ac-13ac5f82e617" />

Wasmline-wasmline-core-plugin.wasm.zip

./wasmtime compile Wasmline-wasmline-core-plugin.wasm -o plugin.cwasm \
--target aarch64-linux-android \
-W gc=y \
-W function-references=y \
-W exceptions=y \
-W simd=n \
-W relaxed-simd=n \
-O static-memory-guard-size=0 \
-O dynamic-memory-guard-size=0 \
-O signals-based-traps=n \
-O opt-level=2 \
-C cranelift-debug-verifier=no

view this post on Zulip Wasmtime GitHub notifications bot (Dec 29 2025 at 17:11):

crowforkotlin edited a comment on issue #12229:

<img width="1739" height="467" alt="Image" src="https://github.com/user-attachments/assets/54509e4b-a92b-4792-a6ac-13ac5f82e617" />

Wasmline-wasmline-core-plugin.wasm.zip

./wasmtime compile Wasmline-wasmline-core-plugin.wasm -o plugin.cwasm \
    --target aarch64-linux-android \
    -W gc=y \
    -W function-references=y \
    -W exceptions=y \
    -W simd=n \
    -W relaxed-simd=n \
    -O static-memory-guard-size=0 \
    -O dynamic-memory-guard-size=0 \
    -O signals-based-traps=n \
    -O opt-level=2 \
    -C cranelift-debug-verifier=no

view this post on Zulip Wasmtime GitHub notifications bot (Dec 29 2025 at 17:16):

crowforkotlin commented on issue #12229:

<img width="2860" height="676" alt="Image" src="https://github.com/user-attachments/assets/c1d23ee4-febb-4cfa-964a-b84c2fd47dd3" />

wasm.zip

view this post on Zulip Wasmtime GitHub notifications bot (Dec 29 2025 at 17:20):

crowforkotlin edited issue #12229:

"Code for function is too large" error and 1.6GB Memory Spike during JIT compilation of a 781KB Kotlin/Wasm module

Environment:

Description:
I am reporting a Compilation error: Code for function is too large that occurs during the JIT loading phase on Android.

Despite the generated .wasm binary being only 781.63 KB, the compilation fails when a single Kotlin function contains a large amount of logic/content. During the attempt to compile this module, I observed a massive RSS memory spike on the Android device, jumping from ~235 MB to over 1.6 GB in just 4 seconds, eventually resulting in the "function too large" error.

Wasmtime Configuration:
The engine is configured specifically for Android compatibility to avoid signal conflicts with ART and minimize VSS overhead:

/**
 * Creates and configures the Wasm Config object.
 *
 * Critical Android Settings:
 * 1. Signals-based traps DISABLED: To prevent conflicts with Android ART signal handlers (SIGSEGV).
 * 2. Memory Guard Size = 0: To prevent VSS (Virtual Set Size) OOM on 32-bit or limited devices.
 * 3. GC / Exceptions: Enabled for Kotlin/Wasm support.
 */
wasm_config_t *Engine::createConfig() {
    wasm_config_t *conf = wasm_config_new();

    // Feature Flags for Kotlin/Wasm support
    wasmtime_config_wasm_gc_set(conf, true);
    wasmtime_config_wasm_function_references_set(conf, true);
    wasmtime_config_wasm_exceptions_set(conf, true);

    // Optimization: Disable SIMD if not strictly needed (improves compatibility)
    wasmtime_config_wasm_simd_set(conf, false);
    wasmtime_config_wasm_relaxed_simd_set(conf, false);

    // [CRITICAL] Disable signal handlers to avoid crash conflicts with Android Runtime (ART)
    wasmtime_config_signals_based_traps_set(conf, false);

    // [CRITICAL] Set guard pages to 0 to minimize Virtual Memory usage (prevents OOM)
    wasmtime_config_memory_guard_size_set(conf, 0);

    // Set max stack size (512KB is usually sufficient for mobile logic)
    wasmtime_config_max_wasm_stack_set(conf, 512 * 1024);

    // Compiler Optimization Strategy: Optimize for Speed and Binary Size
    wasmtime_config_cranelift_opt_level_set(conf, WASMTIME_OPT_LEVEL_SPEED_AND_SIZE);
    wasmtime_config_cranelift_debug_verifier_set(conf, false);

    return conf;
}

Reproduction Steps:

  1. Add a large amount of content/logic into the wasmWasiMain function in Plugin.kt.
  2. Build the wasm file: ./gradlew wasmtime-core:plugin:compileProductionExecutableKotlinWasmWasiOptimize.
  3. The resulting plugin.wasm is ~781 KB.
  4. Load the module on an Android device using the configuration above.

Observed Behavior:

Full Android Logs:

00:49:34.204  I  [MotionEvent] ViewRootImpl windowName 'crow.wasmtime.wasmline/crow.mordecai.wasmline.MainActivity', { action=ACTION_DOWN, id[0]=0, pointerCount=1, eventTime=51746485, downTime=51746485, phoneEventTime=00:49:34.191 } moveCount:0
00:49:34.206  D  getMiuiFreeformStackInfo mTmpFrames.miuiFreeFormStackInfo: null
00:49:34.217  I  CreateGraphicsPipeline pipeline cache hit. elpased time: 0.32 ms.
00:49:34.218  E  FrameInsert open fail: No such file or directory
00:49:34.230  I  This is non sticky GC, maxfree is 33554432 minfree is 8388608
00:49:34.227  W  type=1400 audit(0.0:2008818): avc:  denied  { getopt } for  path="/dev/socket/usap_pool_primary" scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:r:zygote:s0 tclass=unix_stream_socket permissive=0 app=crow.wasmtime.wasmline
00:49:34.322  I  [MotionEvent] ViewRootImpl windowName 'crow.wasmtime.wasmline/crow.mordecai.wasmline.MainActivity', { action=ACTION_UP, id[0]=0, pointerCount=1, eventTime=51746611, downTime=51746485, phoneEventTime=00:49:34.316 } moveCount:0
00:49:34.332  I  ==============================================
00:49:34.337  I  [Android] Wasm file : plugin.wasm    ||    wasm file exits : true    ||    wasm file path :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm
00:49:34.338  I  [Android] Cwasm cache file : plugin.cwasm    ||    cache file exits : false    ||    cache file path :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.cwasm
00:49:34.345  I  [Wasmtime] Module --> Jit Compiling for /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm...
00:49:34.363  W  type=1400 audit(0.0:2008819): avc:  denied  { read } for  name="cpu.cfs_quota_us" dev="cgroup" ino=64 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008820): avc:  denied  { read } for  name="cpu.cfs_period_us" dev="cgroup" ino=65 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008821): avc:  denied  { read } for  name="cpu.cfs_quota_us" dev="cgroup" ino=10 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.363  W  type=1400 audit(0.0:2008822): avc:  denied  { read } for  name="cpu.cfs_period_us" dev="cgroup" ino=11 scontext=u:r:untrusted_app:s0:c190,c257,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=crow.wasmtime.wasmline
00:49:34.441  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 234952kb -> 342100kb
00:49:34.494  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 342100kb -> 428844kb
00:49:34.544  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 428844kb -> 541612kb
00:49:34.602  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 541612kb -> 657240kb
00:49:34.928  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 657240kb -> 860432kb
00:49:35.761  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 860432kb -> 959324kb
00:49:36.012  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 959324kb -> 1075892kb
00:49:36.184  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1075892kb -> 1183820kb
00:49:37.835  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1183820kb -> 1306888kb
00:49:38.482  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1306888kb -> 1450064kb
00:49:38.639  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1450064kb -> 1612484kb
00:49:38.700  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1612484kb -> 1389664kb
00:49:38.700  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1389664kb -> 1011816kb
00:49:38.702  E  [Wasmtime] Module --> Error loading module /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm: Compilation error: Code for function is too large
00:49:38.708  I  [Wasmline] Load failure, because native load return false, file path is :  /data/user/0/crow.wasmtime.wasmline/cache/plugin.wasm
00:49:38.790  E  ->pid:19641,processName:"crow.wasmtime.wasmline",Rss Memory Size Change 1011816kb -> 727648kb

Artifacts:
Wasmline-wasmline-core-plugin.wasm.zip

Analysis & Questions:

  1. Why does a relatively small Wasm file (under 1MB) trigger a "Code too large" error? It seems the Kotlin/Wasm compiler is generating a single function with extremely high complexity.
  2. The memory usage spike to 1.6GB suggests that Cranelift might be hitting a worst-case scenario in its e-graph optimization or register allocation phase.
  3. Are there any specific Cranelift settings to mitigate this, or is this a fundamental limit on function complexity regardless of the total .wasm file size?

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 01:37):

cfallin commented on issue #12229:

Just an FYI -- I am on PTO and then at a conference, so I will be able to investigate this starting Mon, Jan 12. (Thanks for the report!)

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 03:20):

cfallin commented on issue #12229:

Actually, this was bothering me and I at least wanted to verify, so I double-checked with your provided Wasm module and the command

./wasmtime compile Wasmline-wasmline-core-plugin.wasm -o plugin.cwasm \
    --target aarch64-linux-android \
    -W gc=y \
    -W function-references=y \
    -W exceptions=y \
    -W simd=n \
    -W relaxed-simd=n \
    -O static-memory-guard-size=0 \
    -O dynamic-memory-guard-size=0 \
    -O signals-based-traps=n \
    -O opt-level=2 \
    -C cranelift-debug-verifier=no

However, both with a wasmtime built from main (b5272a5f103053f5ada2a38d5302a8d1e2de442d) and from just before the 40.0 branch was cut (ac3358b1c9a1b4ca2794236966e47946d76606ea), running on macOS/aarch64 as you specify, I see the command complete just fine with minimal time taken, and definitely no "Code for function is too large" error -- e.g. from time,

target/release/wasmtime compile Wasmline-wasmline-core-plugin.wasm -o    -W    0.38s user 0.03s system 328% cpu 0.126 total

Am I missing some setting? I'm inclined to close as "cannot reproduce" if not but want to make sure I'm running exactly what you are.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 03:25):

crowforkotlin commented on issue #12229:

Actually, this was bothering me and I at least wanted to verify, so I double-checked with your provided Wasm module and the command实际上,这让我感到困扰,至少我想验证一下,所以我用你提供的 Wasm 模块和命令进行了双重检查。

./wasmtime compile Wasmline-wasmline-core-plugin.wasm -o plugin.cwasm \ --target aarch64-linux-android \ -W gc=y \ -W function-references=y \ -W exceptions=y \ -W simd=n \ -W relaxed-simd=n \ -O static-memory-guard-size=0 \ -O dynamic-memory-guard-size=0 \ -O signals-based-traps=n \ -O opt-level=2 \ -C cranelift-debug-verifier=no

However, both with a wasmtime built from main (b5272a5) and from just before the 40.0 branch was cut (ac3358b), running on macOS/aarch64 as you specify, I see the command complete just fine with minimal time taken, and definitely no "Code for function is too large" error -- e.g. from time,然而,无论使用从 main ()构建的 wasmtime 还是从 40.0 分支之前构建的 wasmtime,在您指定的 macOS/aarch64 上运行时,命令都能正常完成,时间非常短,绝对没有“函数代码太长”的错误提示 - 例如,从 time

target/release/wasmtime compile Wasmline-wasmline-core-plugin.wasm -o -W 0.38s user 0.03s system 328% cpu 0.126 total

Am I missing some setting? I'm inclined to close as "cannot reproduce" if not but want to make sure I'm running exactly what you are.我是不是漏掉了什么设置?如果不是的话,我倾向于关闭为“无法重现”,但还是想确保我正在运行的是你所要求的。

The file download was incorrect. You used a WASM file generated from a small amount of code; it was my oversight for sending it to the wrong location. While the CWASM generated from that file works fine, using the larger WASM file (700KB+) to generate a CWASM triggers an exception. I’m sending you the latest version now for you to check.

wasm.zip

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 03:29):

crowforkotlin commented on issue #12229:

Actually, this was bothering me and I at least wanted to verify, so I double-checked with your provided Wasm module and the command实际上,这让我感到困扰,至少我想验证一下,所以我用你提供的 Wasm 模块和命令进行了双重检查。实际上,这让我感到困扰,至少我想验证一下,所以我用你提供的 Wasm 模块和命令进行了双重检查。
./wasmtime compile Wasmline-wasmline-core-plugin.wasm -o plugin.cwasm \ --target aarch64-linux-android \ -W gc=y \ -W function-references=y \ -W exceptions=y \ -W simd=n \ -W relaxed-simd=n \ -O static-memory-guard-size=0 \ -O dynamic-memory-guard-size=0 \ -O signals-based-traps=n \ -O opt-level=2 \ -C cranelift-debug-verifier=no

However, both with a wasmtime built from main (b5272a5) and from just before the 40.0 branch was cut (ac3358b), running on macOS/aarch64 as you specify, I see the command complete just fine with minimal time taken, and definitely no "Code for function is too large" error -- e.g. from time,然而,无论使用从 main ()构建的 wasmtime 还是从 40.0 分支之前构建的 wasmtime,在您指定的 macOS/aarch64 上运行时,命令都能正常完成,时间非常短,绝对没有“函数代码太长”的错误提示 - 例如,从 time。然而,无论使用从 main ()构建的 wasmtime 还是从 40.0 分支之前构建的 wasmtime,在您指定的 macOS/aarch64 上运行时,命令都能正常完成,时间非常短,绝对没有“函数代码太长”的错误提示 - 例如,从 time
target/release/wasmtime compile Wasmline-wasmline-core-plugin.wasm -o -W 0.38s user 0.03s system 328% cpu 0.126 total

Am I missing some setting? I'm inclined to close as "cannot reproduce" if not but want to make sure I'm running exactly what you are.我是不是漏掉了什么设置?如果不是的话,我倾向于关闭为“无法重现”,但还是想确保我正在运行的是你所要求的。我是不是漏掉了什么设置?如果不是的话,我倾向于关闭为“无法重现”,但还是想确保我正在运行的是你所要求的。

The file download was incorrect. You used a WASM file generated from a small amount of code; it was my oversight for sending it to the wrong location. While the CWASM generated from that file works fine, using the larger WASM file (700KB+) to generate a CWASM triggers an exception. I’m sending you the latest version now for you to check.文件下载不正确。您使用了一个来自少量代码生成的 WASM 文件;这是我的疏忽,将它发送到错误的位置。虽然从该文件生成的 CWASM 文件正常工作,但使用更大的 WASM 文件(700KB+)生成 CWASM 会触发异常。我现在将为您发送最新版本。

wasm.zip

The Kotlin/WASI build process uses Gradle tasks to generate WASM artifacts. The output ZIP includes 'kotlin' and 'optimize' folders, which seem to act as a size-optimization toggle similar to a release environment switch.[1] Yesterday, I inspected the WASM file with wasmtime-tools and discovered it contains over 22,000 global variables.[1] I realize this is not an ideal implementation, but I'm concerned that if a user implements extensive logic in the future, the resulting large file size might trigger exceptions during CWASM generation.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 03:30):

crowforkotlin deleted a comment on issue #12229:

Actually, this was bothering me and I at least wanted to verify, so I double-checked with your provided Wasm module and the command实际上,这让我感到困扰,至少我想验证一下,所以我用你提供的 Wasm 模块和命令进行了双重检查。

./wasmtime compile Wasmline-wasmline-core-plugin.wasm -o plugin.cwasm \ --target aarch64-linux-android \ -W gc=y \ -W function-references=y \ -W exceptions=y \ -W simd=n \ -W relaxed-simd=n \ -O static-memory-guard-size=0 \ -O dynamic-memory-guard-size=0 \ -O signals-based-traps=n \ -O opt-level=2 \ -C cranelift-debug-verifier=no

However, both with a wasmtime built from main (b5272a5) and from just before the 40.0 branch was cut (ac3358b), running on macOS/aarch64 as you specify, I see the command complete just fine with minimal time taken, and definitely no "Code for function is too large" error -- e.g. from time,然而,无论使用从 main ()构建的 wasmtime 还是从 40.0 分支之前构建的 wasmtime,在您指定的 macOS/aarch64 上运行时,命令都能正常完成,时间非常短,绝对没有“函数代码太长”的错误提示 - 例如,从 time

target/release/wasmtime compile Wasmline-wasmline-core-plugin.wasm -o -W 0.38s user 0.03s system 328% cpu 0.126 total

Am I missing some setting? I'm inclined to close as "cannot reproduce" if not but want to make sure I'm running exactly what you are.我是不是漏掉了什么设置?如果不是的话,我倾向于关闭为“无法重现”,但还是想确保我正在运行的是你所要求的。

The file download was incorrect. You used a WASM file generated from a small amount of code; it was my oversight for sending it to the wrong location. While the CWASM generated from that file works fine, using the larger WASM file (700KB+) to generate a CWASM triggers an exception. I’m sending you the latest version now for you to check.

wasm.zip

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 03:31):

crowforkotlin edited a comment on issue #12229:

Actually, this was bothering me and I at least wanted to verify, so I double-checked with your provided Wasm module and the command实际上,这让我感到困扰,至少我想验证一下,所以我用你提供的 Wasm 模块和命令进行了双重检查。实际上,这让我感到困扰,至少我想验证一下,所以我用你提供的 Wasm 模块和命令进行了双重检查。
./wasmtime compile Wasmline-wasmline-core-plugin.wasm -o plugin.cwasm \ --target aarch64-linux-android \ -W gc=y \ -W function-references=y \ -W exceptions=y \ -W simd=n \ -W relaxed-simd=n \ -O static-memory-guard-size=0 \ -O dynamic-memory-guard-size=0 \ -O signals-based-traps=n \ -O opt-level=2 \ -C cranelift-debug-verifier=no

However, both with a wasmtime built from main (b5272a5) and from just before the 40.0 branch was cut (ac3358b), running on macOS/aarch64 as you specify, I see the command complete just fine with minimal time taken, and definitely no "Code for function is too large" error -- e.g. from time,然而,无论使用从 main ()构建的 wasmtime 还是从 40.0 分支之前构建的 wasmtime,在您指定的 macOS/aarch64 上运行时,命令都能正常完成,时间非常短,绝对没有“函数代码太长”的错误提示 - 例如,从 time。然而,无论使用从 main ()构建的 wasmtime 还是从 40.0 分支之前构建的 wasmtime,在您指定的 macOS/aarch64 上运行时,命令都能正常完成,时间非常短,绝对没有“函数代码太长”的错误提示 - 例如,从 time
target/release/wasmtime compile Wasmline-wasmline-core-plugin.wasm -o -W 0.38s user 0.03s system 328% cpu 0.126 total

Am I missing some setting? I'm inclined to close as "cannot reproduce" if not but want to make sure I'm running exactly what you are.我是不是漏掉了什么设置?如果不是的话,我倾向于关闭为“无法重现”,但还是想确保我正在运行的是你所要求的。我是不是漏掉了什么设置?如果不是的话,我倾向于关闭为“无法重现”,但还是想确保我正在运行的是你所要求的。

The file download was incorrect. You used a WASM file generated from a small amount of code; it was my oversight for sending it to the wrong location. While the CWASM generated from that file works fine, using the larger WASM file (700KB+) to generate a CWASM triggers an exception. I’m sending you the latest version now for you to check.文件下载不正确。您使用了一个来自少量代码生成的 WASM 文件;这是我的疏忽,将它发送到错误的位置。虽然从该文件生成的 CWASM 文件正常工作,但使用更大的 WASM 文件(700KB+)生成 CWASM 会触发异常。我现在将为您发送最新版本。

wasm.zip

The Kotlin/WASI build process uses Gradle tasks to generate WASM artifacts. The output ZIP includes 'kotlin' and 'optimize' folders, which seem to act as a size-optimization toggle similar to a release environment switch.[1] Yesterday, I inspected the WASM file with wasmtime-tools and discovered it contains over 22,000 global variables.[1] I realize this is not an ideal implementation, but I'm concerned that if a user implements extensive logic in the future, the resulting large file size might trigger exceptions during CWASM generation.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 04:27):

cfallin commented on issue #12229:

Thanks for that. A few stats from your optimized/Wasmline-wasmline-core-plugin.wasm in your latest zip file, function 127 in the module:

22433 global.get
16819 call
11238 i32.const
5612 global.set
5608 struct.new
  20 local.get
  12 struct.set
   9 end
   7 local.set
   7 drop
   6 ref.null
   6 ref.is_null
   6 local.tee
   6 if
   2 block
   1 unreachable
   1 try_table
   1 throw_ref
   1 br
   1 array.new_data

So, my thoughts:

The immediate issue is that lowering runs out of VRegs, for which we allow only 2M (2^21), because of bitpacking for efficiency. We could in theory look at increasing that. But at least we are returning a clean error ("function too large") rather than panic'ing.

On a broader scale, I don't think Cranelift (or any optimizing backend) is going to meet your requirements/expectations if that is the code that you need to compile. I would thus recommend either:

cc @fitzgen for any thoughts on struct.new...

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 07:20):

crowforkotlin commented on issue #12229:

Hello, could you please share how you generated this histogram? I’d like to learn the method to help with my future debugging.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 07:59):

crowforkotlin deleted a comment on issue #12229:

Hello, could you please share how you generated this histogram? I’d like to learn the method to help with my future debugging.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 30 2025 at 09:33):

crowforkotlin commented on issue #12229:

Interestingly, after refining my Kotlin/Wasm (WASI) implementation, a 700KB Wasm file successfully compiled into a 28MB CWASM via JIT without triggering the "Code for function is too large" error. I suspect the Kotlin/Wasm compiler might be performing aggressive inlining, potentially collapsing numerous function implementations into a single entry point (e.g., the main function). If this aggressive inlining could be disabled or tuned, the issue might be resolved. For context, I have successfully tested the build and execution on an Android app.
Additionally, I have a question regarding Wasmtime: is there a hard limit of 2 million virtual registers? I’m trying to understand if this issue stems from the generation of approximately 4 million (4M) virtual register values.
I am planning to report this to the Kotlin team with the relevant details. While I am not entirely certain about the underlying mechanism, the issue is consistently reproducible.

wasm-success-size28mb.zip

@cfallin

view this post on Zulip Wasmtime GitHub notifications bot (Dec 31 2025 at 19:18):

fitzgen commented on issue #12229:

struct.new in particular is expanding to a lot of IR, because of its inlined fast-path. I don't think that's the wrong choice though -- it makes sense to make allocation fast for the usual program structure that has maybe a few allocation sites per function, rather than try to optimize for code size for the uncommon case of a single function with 5608 struct.news (!).

We could possibly have a fuel counter for inlining the GC allocation fast path, and start deferring to out-of-line calls once the fuel is spent. This is nice because we already have out-of-line paths for allocation that we can reuse.

Except... the (default) DRC collector already does allocation out-of-line; it only does field initialization inline. I expect that it is this field initialization that is what is blowing up the CLIF size relative to the input Wasm size. The DRC collector's barriers are not small.

That said, we don't have any existing code path to do allocation and field initialization out of line, so adding such a path would be purely new maintenance burden.

Chris, did you check that this function doesn't blow any implementation limits? We should be able to compile anything within those limits in theory (even if it hits slow paths or whatever). Those limits should in theory be caught by wasmparser's validation, but it is always possible we missed something... Looking into this a little more now.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 31 2025 at 19:30):

fitzgen commented on issue #12229:

Chris, did you check that this function doesn't blow any implementation limits? We should be able to compile anything within those limits in theory (even if it hits slow paths or whatever). Those limits should in theory be caught by wasmparser's validation, but it is always possible we missed something... Looking into this a little more now.

I'm not seeing this break any limits, fwiw.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 31 2025 at 20:16):

cfallin commented on issue #12229:

is there a hard limit of 2 million virtual registers? I’m trying to understand if this issue stems from the generation of approximately 4 million (4M) virtual register values.

That's correct. (And yes, this doesn't hit any implementation limits; there are "only" 61k Wasm instructions in the function, which is far below the ~7MB limit.)

I agree that "should be able to compile any function at all within limits without a 'too large' error" is a good goal to have, and is the ideal state to end up in. I also think that's a large project in general: not only the VReg limit (which we could raise today, at a ~few-percent compile time cost) but the blowup in the IR in general is likely going to lead to OOMs etc in worst-cases as long as we have a lot of inlined logic for some operators.

I wonder if it would make sense to have a "small operator footprint" mode where anything nontrivial (more than one or two CLIF operators) becomes a libcall? And then select this mode if the function is too large or contains too many of a certain kind of operator? I guess that's an eager form of your "fuel" idea; starting that way rather than switching partway through. Though fuel seems workable too.

For what it's worth, to ask the usual "what would SpiderMonkey do?" question, it seems that a tier-up heuristic that estimates compilation cost will effectively prevent optimizing compilation if the function body is "too large". So we're in kind of a unique position where the standard Wasm implementation limits are agreed upon by engines that can always fall back to baseline but we must always use the optimizing compiler on every function if we're set up to use it at all. So we're trying to solve a much harder problem (and one that the implementation limits are arguably not designed to guard against).

view this post on Zulip Wasmtime GitHub notifications bot (Jan 01 2026 at 07:57):

crowforkotlin edited a comment on issue #12229:

Actually, this was bothering me and I at least wanted to verify, so I double-checked with your provided Wasm module and the command
./wasmtime compile Wasmline-wasmline-core-plugin.wasm -o plugin.cwasm \ --target aarch64-linux-android \ -W gc=y \ -W function-references=y \ -W exceptions=y \ -W simd=n \ -W relaxed-simd=n \ -O static-memory-guard-size=0 \ -O dynamic-memory-guard-size=0 \ -O signals-based-traps=n \ -O opt-level=2 \ -C cranelift-debug-verifier=no

However, both with a wasmtime built from main (b5272a5) and from just before the 40.0 branch was cut (ac3358b), running on macOS/aarch64 as you specify, I see the command complete just fine with minimal time taken, and definitely no "Code for function is too large" error -- e.g. from time
target/release/wasmtime compile Wasmline-wasmline-core-plugin.wasm -o -W 0.38s user 0.03s system 328% cpu 0.126 total

Am I missing some setting? I'm inclined to close as "cannot reproduce" if not but want to make sure I'm running exactly what you are.

The file download was incorrect. You used a WASM file generated from a small amount of code; it was my oversight for sending it to the wrong location. While the CWASM generated from that file works fine, using the larger WASM file (700KB+) to generate a CWASM triggers an exception. I’m sending you the latest version now for you to check.

wasm.zip

The Kotlin/WASI build process uses Gradle tasks to generate WASM artifacts. The output ZIP includes 'kotlin' and 'optimize' folders, which seem to act as a size-optimization toggle similar to a release environment switch.[1] Yesterday, I inspected the WASM file with wasmtime-tools and discovered it contains over 22,000 global variables.[1] I realize this is not an ideal implementation, but I'm concerned that if a user implements extensive logic in the future, the resulting large file size might trigger exceptions during CWASM generation.

view this post on Zulip Wasmtime GitHub notifications bot (Jan 05 2026 at 15:32):

alexcrichton added the wasm-proposal:gc label to Issue #12229.

view this post on Zulip Wasmtime GitHub notifications bot (Jan 07 2026 at 14:20):

crowforkotlin commented on issue #12229:

I have reported the upstream issue regarding the IR explosion to the Kotlin team (see KT-83497). While we await a fix on their end, I would like to highlight a critical bottleneck in Wasmtime's JIT compilation.
currently, the JIT behavior is unstable for our use case. I observing exponential memory growth when processing these large initialization functions, which rapidly leads to OOM errors. Consequently, I have been forced to migrate my project entirely to AOT compilation to maintain stability.

view this post on Zulip Wasmtime GitHub notifications bot (Jan 07 2026 at 17:47):

fitzgen commented on issue #12229:

@crowforkotlin The JIT and AOT compilation pipelines are identical, the only difference is that when JITing we then map the resulting code as executable into the current process, rather than writing it to disk or giving it to the caller as a Vec<u8>. That is, if you observing exponential memory growth in one, then you should also see it in the other. Can you provide additional details for this new JIT vs AOT issue? Test case, steps to reproduce, etc. Thanks!

view this post on Zulip Wasmtime GitHub notifications bot (Jan 07 2026 at 17:59):

crowforkotlin commented on issue #12229:

@crowforkotlin The JIT and AOT compilation pipelines are identical, the only difference is that when JITing we then map the resulting code as executable into the current process, rather than writing it to disk or giving it to the caller as a Vec<u8>. That is, if you observing exponential memory growth in one, then you should also see it in the other. Can you provide additional details for this new JIT vs AOT issue? Test case, steps to reproduce, etc. Thanks!

Okay, I'll debug and output the details of AOT and JIT on Android when I have some free time in the next couple of days. If you need the sample, you might need to install Android Studio to run the wasmline-sample test cases on a real Android device or emulator. If needed, I can provide remote assistance or technical support to help with setup and running. The sample isn't very complete right now, mainly because I haven't had much time to implement some features. I've been busy researching the removal of features from the wasmtime library, cross-platform building, and stability testing on different platforms.

view this post on Zulip Wasmtime GitHub notifications bot (Jan 07 2026 at 18:03):

crowforkotlin edited a comment on issue #12229:

@crowforkotlin The JIT and AOT compilation pipelines are identical, the only difference is that when JITing we then map the resulting code as executable into the current process, rather than writing it to disk or giving it to the caller as a Vec<u8>. That is, if you observing exponential memory growth in one, then you should also see it in the other. Can you provide additional details for this new JIT vs AOT issue? Test case, steps to reproduce, etc. Thanks!

Okay, I'll debug and output the details of AOT and JIT on Android when I have some free time in the next couple of days. If you need the sample, you might need to install Android Studio to run the wasmline-sample test cases on a real Android device or emulator. If needed, I can provide remote assistance or technical support to help with setup and running. The sample isn't very complete right now, and building it might be tricky for users who aren't familiar with KMP., mainly because I haven't had much time to implement some features. I've been busy researching the removal of features from the wasmtime library, cross-platform building, and stability testing on different platforms.

view this post on Zulip Wasmtime GitHub notifications bot (Jan 07 2026 at 18:30):

cfallin commented on issue #12229:

@crowforkotlin thanks for noting this new issue -- for reference though I don't think we maintainers will be able to install Android Studio and build your project; it would be best if you can provide us with a Wasm or WAT and compilation flags such that this reproduces with wasmtime compile. (For pure compilation issues, none of your other integration details should be relevant.)

view this post on Zulip Wasmtime GitHub notifications bot (Jan 09 2026 at 10:09):

crowforkotlin commented on issue #12229:

  ~/Dow/kotlin-2.3.2/p/optimized  sh check.sh                                                              18:04:12
Starting AOT compilation and resource monitoring...
----------------------------------------------------
        Command being timed: "wasmtime compile ./wasmline-multiplatform-wasmline-sample-plugin.wasm -o ./plugin.cwasm --target aarch64-linux-android -W gc=y -W function-references=y -W exceptions=y -W simd=n -W relaxed-simd=n -O static-memory-guard-size=0 -O dynamic-memory-guard-size=0 -O signals-based-traps=n -O opt-level=2 -C cranelift-debug-verifier=n"
        User time (seconds): 0.00
        System time (seconds): 0.00
        Percent of CPU this job got: 0%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.23
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 5380
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 1411
        Minor (reclaiming a frame) page faults: 0
        Voluntary context switches: 0
        Involuntary context switches: 0
        Swaps: 0
        File system inputs: 0
        File system outputs: 0
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 65536
        Exit status: 0
----------------------------------------------------
Compilation successful: ./plugin.cwasm generated.
  ~/Dow/kotlin-2.3.2/p/optimized  bat -P ./check.sh                                                        18:04:14
#!/bin/bash

# Configuration
SOURCE_WASM="./wasmline-multiplatform-wasmline-sample-plugin.wasm"
OUTPUT_CWASM="./plugin.cwasm"
TARGET="aarch64-linux-android"

echo "Starting AOT compilation and resource monitoring..."
echo "----------------------------------------------------"

# Using /usr/bin/time for detailed resource usage report
# The output will show Peak Memory (RSS) and CPU usage
/usr/bin/time -v wasmtime compile "$SOURCE_WASM" -o "$OUTPUT_CWASM" \
  --target "$TARGET" \
  -W gc=y \
  -W function-references=y \
  -W exceptions=y \
  -W simd=n \
  -W relaxed-simd=n \
  -O static-memory-guard-size=0 \
  -O dynamic-memory-guard-size=0 \
  -O signals-based-traps=n \
  -O opt-level=2 \
  -C cranelift-debug-verifier=n

EXIT_CODE=$?

echo "----------------------------------------------------"
if [ $EXIT_CODE -eq 0 ]; then
    echo "Compilation successful: $OUTPUT_CWASM generated."
else
    echo "Error: Compilation failed with exit code $EXIT_CODE."
fi

https://github.com/user-attachments/assets/4a1f4326-4dc0-4952-a9a8-6cc2d4f5667b

https://github.com/crowforkotlin/wasmline/blob/715f19fbd72f556da6e4a38ff6bb14e0ccda3b14/wasmline-core/src/Module.cpp#L58

if (isJit) {
    LOGI("[Wasmtime] Module --> Jit Compiling for %s...", filePath.c_str());
    error = wasmtime_module_new(engine, data.data(), data.size(), &module);
} else {
    LOGI("[Wasmtime] Module --> Aot Deserializing for %s...", filePath.c_str());
    error = wasmtime_module_deserialize(engine, data.data(), data.size(), &module);
}

view this post on Zulip Wasmtime GitHub notifications bot (Jan 09 2026 at 10:10):

crowforkotlin edited a comment on issue #12229:

  ~/Dow/kotlin-2.3.2/p/optimized  sh check.sh                                                              18:04:12
Starting AOT compilation and resource monitoring...
----------------------------------------------------
        Command being timed: "wasmtime compile ./wasmline-multiplatform-wasmline-sample-plugin.wasm -o ./plugin.cwasm --target aarch64-linux-android -W gc=y -W function-references=y -W exceptions=y -W simd=n -W relaxed-simd=n -O static-memory-guard-size=0 -O dynamic-memory-guard-size=0 -O signals-based-traps=n -O opt-level=2 -C cranelift-debug-verifier=n"
        User time (seconds): 0.00
        System time (seconds): 0.00
        Percent of CPU this job got: 0%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.23
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 5380
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 1411
        Minor (reclaiming a frame) page faults: 0
        Voluntary context switches: 0
        Involuntary context switches: 0
        Swaps: 0
        File system inputs: 0
        File system outputs: 0
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 65536
        Exit status: 0
----------------------------------------------------
Compilation successful: ./plugin.cwasm generated.
  ~/Dow/kotlin-2.3.2/p/optimized  bat -P ./check.sh                                                        18:04:14
#!/bin/bash

# Configuration
SOURCE_WASM="./wasmline-multiplatform-wasmline-sample-plugin.wasm"
OUTPUT_CWASM="./plugin.cwasm"
TARGET="aarch64-linux-android"

echo "Starting AOT compilation and resource monitoring..."
echo "----------------------------------------------------"

# Using /usr/bin/time for detailed resource usage report
# The output will show Peak Memory (RSS) and CPU usage
/usr/bin/time -v wasmtime compile "$SOURCE_WASM" -o "$OUTPUT_CWASM" \
  --target "$TARGET" \
  -W gc=y \
  -W function-references=y \
  -W exceptions=y \
  -W simd=n \
  -W relaxed-simd=n \
  -O static-memory-guard-size=0 \
  -O dynamic-memory-guard-size=0 \
  -O signals-based-traps=n \
  -O opt-level=2 \
  -C cranelift-debug-verifier=n

EXIT_CODE=$?

echo "----------------------------------------------------"
if [ $EXIT_CODE -eq 0 ]; then
    echo "Compilation successful: $OUTPUT_CWASM generated."
else
    echo "Error: Compilation failed with exit code $EXIT_CODE."
fi

https://github.com/user-attachments/assets/4a1f4326-4dc0-4952-a9a8-6cc2d4f5667b

https://github.com/crowforkotlin/wasmline/blob/715f19fbd72f556da6e4a38ff6bb14e0ccda3b14/wasmline-core/src/Module.cpp#L58

if (isJit) {
    LOGI("[Wasmtime] Module --> Jit Compiling for %s...", filePath.c_str());
    error = wasmtime_module_new(engine, data.data(), data.size(), &module);
} else {
    LOGI("[Wasmtime] Module --> Aot Deserializing for %s...", filePath.c_str());
    error = wasmtime_module_deserialize(engine, data.data(), data.size(), &module);
}

wasmtime.zip


Last updated: Jan 09 2026 at 13:15 UTC