Skip to content

Commit fe1a286

Browse files
committed
Simplify indirect call handling without closures
Refactored the compiler to only emit closure environment setup code when the closures feature is enabled. For builds without closures, indirect calls now use a simpler code path, resulting in smaller and cleaner generated code. Updated numerous test outputs to reflect the reduced stack usage and removed unnecessary closure environment handling.
1 parent cc0f4ec commit fe1a286

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+11071
-18564
lines changed

src/compiler.ts

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7267,40 +7267,55 @@ export class Compiler extends DiagnosticEmitter {
72677267
}
72687268
if (operands) this.operandsTostack(signature, operands);
72697269

7270-
// Load the _env field from Function object and store to global for closure access
7271-
let closureEnvGlobal = this.ensureClosureEnvironmentGlobal();
7272-
let usizeSize = this.options.usizeType.byteSize;
7273-
7274-
// Get the offset of _env in the Function class
7275-
// _index is u32 (4 bytes), _env follows at offset 4 (wasm32) or 8 (wasm64 with padding)
7276-
let envOffset = this.options.isWasm64 ? 8 : 4;
7270+
// Only set up closure environment handling when closures feature is enabled
7271+
if (this.options.hasFeature(Feature.Closures)) {
7272+
// Load the _env field from Function object and store to global for closure access
7273+
let closureEnvGlobal = this.ensureClosureEnvironmentGlobal();
7274+
let usizeSize = this.options.usizeType.byteSize;
72777275

7278-
// We need to evaluate functionArg once, store to temp, then use for both _env and _index
7279-
let flow = this.currentFlow;
7280-
let funcTemp = flow.getTempLocal(this.options.usizeType);
7281-
let funcTempIndex = funcTemp.index;
7276+
// Get the offset of _env in the Function class
7277+
// _index is u32 (4 bytes), _env follows at offset 4 (wasm32) or 8 (wasm64 with padding)
7278+
let envOffset = this.options.isWasm64 ? 8 : 4;
72827279

7283-
let stmts: ExpressionRef[] = [
7284-
// Store function pointer to temp
7285-
module.local_set(funcTempIndex, functionArg, true),
7286-
// Store _env to global: $~lib/__closure_env = func._env
7287-
module.global_set(closureEnvGlobal,
7288-
module.load(usizeSize, false,
7289-
module.local_get(funcTempIndex, sizeTypeRef),
7290-
sizeTypeRef,
7291-
envOffset
7280+
// We need to evaluate functionArg once, store to temp, then use for both _env and _index
7281+
let flow = this.currentFlow;
7282+
let funcTemp = flow.getTempLocal(this.options.usizeType);
7283+
let funcTempIndex = funcTemp.index;
7284+
7285+
let stmts: ExpressionRef[] = [
7286+
// Store function pointer to temp
7287+
module.local_set(funcTempIndex, functionArg, true),
7288+
// Store _env to global: $~lib/__closure_env = func._env
7289+
module.global_set(closureEnvGlobal,
7290+
module.load(usizeSize, false,
7291+
module.local_get(funcTempIndex, sizeTypeRef),
7292+
sizeTypeRef,
7293+
envOffset
7294+
)
72927295
)
7293-
)
7294-
];
7296+
];
72957297

7296-
let indexExpr = module.load(4, false,
7297-
module.local_get(funcTempIndex, sizeTypeRef),
7298-
TypeRef.I32 // ._index
7299-
);
7298+
let indexExpr = module.load(4, false,
7299+
module.local_get(funcTempIndex, sizeTypeRef),
7300+
TypeRef.I32 // ._index
7301+
);
7302+
7303+
let expr = module.call_indirect(
7304+
null, // TODO: handle multiple tables
7305+
module.block(null, stmts.concat([indexExpr]), TypeRef.I32),
7306+
operands,
7307+
signature.paramRefs,
7308+
signature.resultRefs
7309+
);
7310+
this.currentType = returnType;
7311+
return expr;
7312+
}
73007313

7314+
// Without closures, use simpler indirect call (just load _index from Function)
7315+
let indexExpr = module.load(4, false, functionArg, TypeRef.I32); // ._index at offset 0
73017316
let expr = module.call_indirect(
7302-
null, // TODO: handle multiple tables
7303-
module.block(null, stmts.concat([indexExpr]), TypeRef.I32),
7317+
null,
7318+
indexExpr,
73047319
operands,
73057320
signature.paramRefs,
73067321
signature.resultRefs

tests/compiler/assert-nonnull.debug.wat

Lines changed: 36 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
(global $~lib/shared/runtime/Runtime.Minimal i32 (i32.const 1))
1010
(global $~lib/shared/runtime/Runtime.Incremental i32 (i32.const 2))
1111
(global $~argumentsLength (mut i32) (i32.const 0))
12-
(global $$~lib/__closure_env (mut i32) (i32.const 0))
1312
(global $~lib/memory/__data_end i32 (i32.const 444))
1413
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 33212))
1514
(global $~lib/memory/__heap_base i32 (i32.const 33212))
@@ -516,28 +515,23 @@
516515
(func $assert-nonnull/testObjFn (param $foo i32) (result i32)
517516
(local $1 i32)
518517
(local $2 i32)
519-
(local $3 i32)
520518
global.get $~lib/memory/__stack_pointer
521-
i32.const 12
519+
i32.const 8
522520
i32.sub
523521
global.set $~lib/memory/__stack_pointer
524522
call $~stack_check
525523
global.get $~lib/memory/__stack_pointer
526524
i64.const 0
527525
i64.store
528-
global.get $~lib/memory/__stack_pointer
529-
i32.const 0
530-
i32.store offset=8
531-
global.get $~lib/memory/__stack_pointer
532526
i32.const 0
533527
global.set $~argumentsLength
534528
global.get $~lib/memory/__stack_pointer
535529
local.get $foo
536-
local.set $3
530+
local.set $2
537531
global.get $~lib/memory/__stack_pointer
538-
local.get $3
532+
local.get $2
539533
i32.store
540-
local.get $3
534+
local.get $2
541535
call $assert-nonnull/Foo#get:baz
542536
local.tee $1
543537
i32.store offset=4
@@ -552,49 +546,41 @@
552546
call $~lib/builtins/abort
553547
unreachable
554548
end
555-
local.tee $2
556-
i32.store offset=8
557-
local.get $2
558-
i32.load offset=4
559-
global.set $$~lib/__closure_env
560-
local.get $2
561549
i32.load
562550
call_indirect (type $1)
563-
local.set $3
551+
local.set $2
564552
global.get $~lib/memory/__stack_pointer
565-
i32.const 12
553+
i32.const 8
566554
i32.add
567555
global.set $~lib/memory/__stack_pointer
568-
local.get $3
556+
local.get $2
569557
return
570558
)
571559
(func $assert-nonnull/testObjRet (param $foo i32) (result i32)
572560
(local $1 i32)
573561
(local $2 i32)
574562
(local $3 i32)
575-
(local $4 i32)
576563
global.get $~lib/memory/__stack_pointer
577-
i32.const 16
564+
i32.const 12
578565
i32.sub
579566
global.set $~lib/memory/__stack_pointer
580567
call $~stack_check
581568
global.get $~lib/memory/__stack_pointer
582569
i64.const 0
583570
i64.store
584571
global.get $~lib/memory/__stack_pointer
585-
i64.const 0
586-
i64.store offset=8
587-
global.get $~lib/memory/__stack_pointer
572+
i32.const 0
573+
i32.store offset=8
588574
global.get $~lib/memory/__stack_pointer
589575
i32.const 0
590576
global.set $~argumentsLength
591577
global.get $~lib/memory/__stack_pointer
592578
local.get $foo
593-
local.set $4
579+
local.set $3
594580
global.get $~lib/memory/__stack_pointer
595-
local.get $4
581+
local.get $3
596582
i32.store
597-
local.get $4
583+
local.get $3
598584
call $assert-nonnull/Foo#get:baz
599585
local.tee $1
600586
i32.store offset=4
@@ -609,19 +595,13 @@
609595
call $~lib/builtins/abort
610596
unreachable
611597
end
598+
i32.load
599+
call_indirect (type $1)
612600
local.tee $2
613601
i32.store offset=8
614602
local.get $2
615-
i32.load offset=4
616-
global.set $$~lib/__closure_env
617-
local.get $2
618-
i32.load
619-
call_indirect (type $1)
620-
local.tee $3
621-
i32.store offset=12
622-
local.get $3
623603
if (result i32)
624-
local.get $3
604+
local.get $2
625605
else
626606
i32.const 32
627607
i32.const 160
@@ -630,12 +610,12 @@
630610
call $~lib/builtins/abort
631611
unreachable
632612
end
633-
local.set $4
613+
local.set $3
634614
global.get $~lib/memory/__stack_pointer
635-
i32.const 16
615+
i32.const 12
636616
i32.add
637617
global.set $~lib/memory/__stack_pointer
638-
local.get $4
618+
local.get $3
639619
return
640620
)
641621
(func $assert-nonnull/testVar (param $n i32) (result i32)
@@ -675,16 +655,14 @@
675655
(func $assert-nonnull/testFn (param $fn i32) (result i32)
676656
(local $1 i32)
677657
(local $2 i32)
678-
(local $3 i32)
679658
global.get $~lib/memory/__stack_pointer
680-
i32.const 8
659+
i32.const 4
681660
i32.sub
682661
global.set $~lib/memory/__stack_pointer
683662
call $~stack_check
684663
global.get $~lib/memory/__stack_pointer
685-
i64.const 0
686-
i64.store
687-
global.get $~lib/memory/__stack_pointer
664+
i32.const 0
665+
i32.store
688666
i32.const 0
689667
global.set $~argumentsLength
690668
global.get $~lib/memory/__stack_pointer
@@ -702,39 +680,29 @@
702680
call $~lib/builtins/abort
703681
unreachable
704682
end
705-
local.tee $2
706-
i32.store offset=4
707-
local.get $2
708-
i32.load offset=4
709-
global.set $$~lib/__closure_env
710-
local.get $2
711683
i32.load
712684
call_indirect (type $1)
713-
local.set $3
685+
local.set $2
714686
global.get $~lib/memory/__stack_pointer
715-
i32.const 8
687+
i32.const 4
716688
i32.add
717689
global.set $~lib/memory/__stack_pointer
718-
local.get $3
690+
local.get $2
719691
return
720692
)
721693
(func $assert-nonnull/testFn2 (param $fn i32) (result i32)
722694
(local $1 i32)
723695
(local $fn2 i32)
724696
(local $3 i32)
725-
(local $4 i32)
726697
global.get $~lib/memory/__stack_pointer
727-
i32.const 12
698+
i32.const 8
728699
i32.sub
729700
global.set $~lib/memory/__stack_pointer
730701
call $~stack_check
731702
global.get $~lib/memory/__stack_pointer
732703
i64.const 0
733704
i64.store
734705
global.get $~lib/memory/__stack_pointer
735-
i32.const 0
736-
i32.store offset=8
737-
global.get $~lib/memory/__stack_pointer
738706
global.get $~lib/memory/__stack_pointer
739707
local.get $fn
740708
local.tee $1
@@ -752,33 +720,25 @@
752720
end
753721
local.tee $fn2
754722
i32.store offset=4
755-
global.get $~lib/memory/__stack_pointer
756723
i32.const 0
757724
global.set $~argumentsLength
758725
local.get $fn2
759-
local.tee $3
760-
i32.store offset=8
761-
local.get $3
762-
i32.load offset=4
763-
global.set $$~lib/__closure_env
764-
local.get $3
765726
i32.load
766727
call_indirect (type $1)
767-
local.set $4
728+
local.set $3
768729
global.get $~lib/memory/__stack_pointer
769-
i32.const 12
730+
i32.const 8
770731
i32.add
771732
global.set $~lib/memory/__stack_pointer
772-
local.get $4
733+
local.get $3
773734
return
774735
)
775736
(func $assert-nonnull/testRet (param $fn i32) (result i32)
776737
(local $1 i32)
777738
(local $2 i32)
778739
(local $3 i32)
779-
(local $4 i32)
780740
global.get $~lib/memory/__stack_pointer
781-
i32.const 12
741+
i32.const 8
782742
i32.sub
783743
global.set $~lib/memory/__stack_pointer
784744
call $~stack_check
@@ -787,10 +747,6 @@
787747
i64.store
788748
global.get $~lib/memory/__stack_pointer
789749
i32.const 0
790-
i32.store offset=8
791-
global.get $~lib/memory/__stack_pointer
792-
global.get $~lib/memory/__stack_pointer
793-
i32.const 0
794750
global.set $~argumentsLength
795751
global.get $~lib/memory/__stack_pointer
796752
local.get $fn
@@ -807,19 +763,13 @@
807763
call $~lib/builtins/abort
808764
unreachable
809765
end
766+
i32.load
767+
call_indirect (type $1)
810768
local.tee $2
811769
i32.store offset=4
812770
local.get $2
813-
i32.load offset=4
814-
global.set $$~lib/__closure_env
815-
local.get $2
816-
i32.load
817-
call_indirect (type $1)
818-
local.tee $3
819-
i32.store offset=8
820-
local.get $3
821771
if (result i32)
822-
local.get $3
772+
local.get $2
823773
else
824774
i32.const 32
825775
i32.const 160
@@ -828,12 +778,12 @@
828778
call $~lib/builtins/abort
829779
unreachable
830780
end
831-
local.set $4
781+
local.set $3
832782
global.get $~lib/memory/__stack_pointer
833-
i32.const 12
783+
i32.const 8
834784
i32.add
835785
global.set $~lib/memory/__stack_pointer
836-
local.get $4
786+
local.get $3
837787
return
838788
)
839789
(func $export:assert-nonnull/testVar (param $0 i32) (result i32)

0 commit comments

Comments
 (0)