Skip to content

Commit f6683d6

Browse files
committed
Refactor closure capture analysis and recompilation logic
Replaces the pre-scan approach for closure variable capture with a single-pass, on-demand capture analysis that supports late discovery and recompilation of function bodies when captures are detected after initial compilation. This change simplifies closure handling, ensures correct environment slot assignment, and improves support for complex nested closure scenarios. Updates related logic for local variable tracking, anonymous function naming, and closure environment allocation.
1 parent bc725a4 commit f6683d6

12 files changed

+11138
-1180
lines changed

src/compiler.ts

Lines changed: 358 additions & 778 deletions
Large diffs are not rendered by default.

src/program.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3639,6 +3639,9 @@ export class Local extends VariableLikeElement {
36393639
/** The function whose environment this local is stored in. Set when captured. */
36403640
envOwner: Function | null = null;
36413641

3642+
/** Whether this local was accessed as a regular wasm local (before capture was discovered). */
3643+
wasAccessedAsLocal: bool = false;
3644+
36423645
/** Constructs a new local variable. */
36433646
constructor(
36443647
/** Simple name. */
@@ -3814,8 +3817,8 @@ export class Function extends TypedElement {
38143817
* This is needed because indirect calls can overwrite the global. */
38153818
closureEnvLocal: Local | null = null;
38163819

3817-
/** Pre-scanned names of captured variables (set before compilation, used to mark locals). */
3818-
preCapturedNames: Set<string> | null = null;
3820+
/** Whether this function needs recompilation due to late capture discovery. */
3821+
needsCaptureRecompile: bool = false;
38193822

38203823
/** Whether this function requires an environment (is a closure). */
38213824
get needsEnvironment(): bool {

tests/compiler/closure-class.debug.wat

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2511,13 +2511,13 @@
25112511
i32.const 0
25122512
i32.store
25132513
local.get $$env
2514-
local.get $operand
2514+
local.get $operation
25152515
i32.store offset=4
25162516
local.get $$env
2517-
local.get $operation
2517+
local.get $this
25182518
i32.store offset=8
25192519
local.get $$env
2520-
local.get $this
2520+
local.get $operand
25212521
i32.store offset=12
25222522
i32.const 8
25232523
i32.const 6
@@ -3654,10 +3654,10 @@
36543654
i32.const 0
36553655
i32.store
36563656
local.get $$env
3657-
local.get $amount
3657+
local.get $this
36583658
i32.store offset=4
36593659
local.get $$env
3660-
local.get $this
3660+
local.get $amount
36613661
i32.store offset=8
36623662
i32.const 8
36633663
i32.const 34
@@ -3682,10 +3682,10 @@
36823682
i32.const 0
36833683
i32.store
36843684
local.get $$env
3685-
local.get $factor
3685+
local.get $this
36863686
i32.store offset=4
36873687
local.get $$env
3688-
local.get $this
3688+
local.get $factor
36893689
i32.store offset=8
36903690
i32.const 8
36913691
i32.const 34
@@ -5898,84 +5898,84 @@
58985898
global.get $~lib/__closure_env
58995899
local.set $$closureEnv
59005900
local.get $$closureEnv
5901-
i32.load offset=8
5901+
i32.load offset=4
59025902
i32.const 0
59035903
i32.eq
59045904
if
59055905
local.get $$closureEnv
5906-
i32.load offset=12
5906+
i32.load offset=8
59075907
local.set $1
59085908
global.get $~lib/memory/__stack_pointer
59095909
local.get $1
59105910
i32.store
59115911
local.get $1
59125912
local.get $$closureEnv
5913-
i32.load offset=12
5913+
i32.load offset=8
59145914
local.set $1
59155915
global.get $~lib/memory/__stack_pointer
59165916
local.get $1
59175917
i32.store offset=4
59185918
local.get $1
59195919
call $closure-class/Calculator#get:result
59205920
local.get $$closureEnv
5921-
i32.load offset=4
5921+
i32.load offset=12
59225922
i32.add
59235923
call $closure-class/Calculator#set:result
59245924
else
59255925
local.get $$closureEnv
5926-
i32.load offset=8
5926+
i32.load offset=4
59275927
i32.const 1
59285928
i32.eq
59295929
if
59305930
local.get $$closureEnv
5931-
i32.load offset=12
5931+
i32.load offset=8
59325932
local.set $1
59335933
global.get $~lib/memory/__stack_pointer
59345934
local.get $1
59355935
i32.store
59365936
local.get $1
59375937
local.get $$closureEnv
5938-
i32.load offset=12
5938+
i32.load offset=8
59395939
local.set $1
59405940
global.get $~lib/memory/__stack_pointer
59415941
local.get $1
59425942
i32.store offset=4
59435943
local.get $1
59445944
call $closure-class/Calculator#get:result
59455945
local.get $$closureEnv
5946-
i32.load offset=4
5946+
i32.load offset=12
59475947
i32.sub
59485948
call $closure-class/Calculator#set:result
59495949
else
59505950
local.get $$closureEnv
5951-
i32.load offset=8
5951+
i32.load offset=4
59525952
i32.const 2
59535953
i32.eq
59545954
if
59555955
local.get $$closureEnv
5956-
i32.load offset=12
5956+
i32.load offset=8
59575957
local.set $1
59585958
global.get $~lib/memory/__stack_pointer
59595959
local.get $1
59605960
i32.store
59615961
local.get $1
59625962
local.get $$closureEnv
5963-
i32.load offset=12
5963+
i32.load offset=8
59645964
local.set $1
59655965
global.get $~lib/memory/__stack_pointer
59665966
local.get $1
59675967
i32.store offset=4
59685968
local.get $1
59695969
call $closure-class/Calculator#get:result
59705970
local.get $$closureEnv
5971-
i32.load offset=4
5971+
i32.load offset=12
59725972
i32.mul
59735973
call $closure-class/Calculator#set:result
59745974
end
59755975
end
59765976
end
59775977
local.get $$closureEnv
5978-
i32.load offset=12
5978+
i32.load offset=8
59795979
local.set $1
59805980
global.get $~lib/memory/__stack_pointer
59815981
local.get $1
@@ -10358,26 +10358,26 @@
1035810358
global.get $~lib/__closure_env
1035910359
local.set $$closureEnv
1036010360
local.get $$closureEnv
10361-
i32.load offset=8
10361+
i32.load offset=4
1036210362
local.set $1
1036310363
global.get $~lib/memory/__stack_pointer
1036410364
local.get $1
1036510365
i32.store
1036610366
local.get $1
1036710367
local.get $$closureEnv
10368-
i32.load offset=8
10368+
i32.load offset=4
1036910369
local.set $1
1037010370
global.get $~lib/memory/__stack_pointer
1037110371
local.get $1
1037210372
i32.store offset=4
1037310373
local.get $1
1037410374
call $closure-class/ChainableCounter#get:count
1037510375
local.get $$closureEnv
10376-
i32.load offset=4
10376+
i32.load offset=8
1037710377
i32.add
1037810378
call $closure-class/ChainableCounter#set:count
1037910379
local.get $$closureEnv
10380-
i32.load offset=8
10380+
i32.load offset=4
1038110381
local.set $1
1038210382
global.get $~lib/memory/__stack_pointer
1038310383
i32.const 8
@@ -10400,26 +10400,26 @@
1040010400
global.get $~lib/__closure_env
1040110401
local.set $$closureEnv
1040210402
local.get $$closureEnv
10403-
i32.load offset=8
10403+
i32.load offset=4
1040410404
local.set $1
1040510405
global.get $~lib/memory/__stack_pointer
1040610406
local.get $1
1040710407
i32.store
1040810408
local.get $1
1040910409
local.get $$closureEnv
10410-
i32.load offset=8
10410+
i32.load offset=4
1041110411
local.set $1
1041210412
global.get $~lib/memory/__stack_pointer
1041310413
local.get $1
1041410414
i32.store offset=4
1041510415
local.get $1
1041610416
call $closure-class/ChainableCounter#get:count
1041710417
local.get $$closureEnv
10418-
i32.load offset=4
10418+
i32.load offset=8
1041910419
i32.mul
1042010420
call $closure-class/ChainableCounter#set:count
1042110421
local.get $$closureEnv
10422-
i32.load offset=8
10422+
i32.load offset=4
1042310423
local.set $1
1042410424
global.get $~lib/memory/__stack_pointer
1042510425
i32.const 8
@@ -10819,11 +10819,11 @@
1081910819
return
1082010820
)
1082110821
(func $closure-class/testTaskCallbacks (result i32)
10822+
(local $$env i32)
1082210823
(local $task i32)
1082310824
(local $then i32)
1082410825
(local $complete i32)
1082510826
(local $receivedValue i32)
10826-
(local $$env i32)
1082710827
(local $5 i32)
1082810828
(local $6 i32)
1082910829
(local $7 i32)
@@ -10969,12 +10969,12 @@
1096910969
return
1097010970
)
1097110971
(func $closure-class/testTaskCallbackAfterComplete (result i32)
10972+
(local $$env i32)
1097210973
(local $task i32)
1097310974
(local $then i32)
1097410975
(local $complete i32)
10975-
(local $3 i32)
10976+
(local $4 i32)
1097610977
(local $receivedValue i32)
10977-
(local $$env i32)
1097810978
(local $6 i32)
1097910979
(local $7 i32)
1098010980
(local $8 i32)
@@ -11023,12 +11023,12 @@
1102311023
i32.const 1
1102411024
global.set $~argumentsLength
1102511025
local.get $complete
11026-
local.tee $3
11026+
local.tee $4
1102711027
i32.store offset=16
11028-
local.get $3
11028+
local.get $4
1102911029
i32.load offset=4
1103011030
global.set $~lib/__closure_env
11031-
local.get $3
11031+
local.get $4
1103211032
i32.load
1103311033
call_indirect (type $3)
1103411034
local.get $$env

0 commit comments

Comments
 (0)