Skip to content

Commit 1f611c6

Browse files
authored
fix: Account for virtual stub finalization discovering more virtual calls (AssemblyScript#1569)
1 parent d568e82 commit 1f611c6

File tree

4 files changed

+242
-5
lines changed

4 files changed

+242
-5
lines changed

src/compiler.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,13 @@ export class Compiler extends DiagnosticEmitter {
530530
}
531531
}
532532
var virtualCalls = this.virtualCalls;
533-
for (let _values = Set_values(virtualCalls), i = 0, k = _values.length; i < k; ++i) {
534-
let instance = unchecked(_values[i]);
535-
this.finalizeVirtualStub(instance);
533+
while (virtualCalls.size) {
534+
// finalizing a stub may discover more virtual calls, so do this in a loop
535+
for (let _values = Set_values(virtualCalls), i = 0, k = _values.length; i < k; ++i) {
536+
let instance = unchecked(_values[i]);
537+
this.finalizeVirtualStub(instance);
538+
virtualCalls.delete(instance);
539+
}
536540
}
537541

538542
// finalize runtime features

tests/compiler/class-overloading.optimized.wat

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
(data (i32.const 1228) "\02\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00F")
1515
(data (i32.const 1260) "\04\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\04\00\00\00I\00B")
1616
(data (i32.const 1292) "\04\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\04\00\00\00I\00C")
17+
(data (i32.const 1324) "\1e\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\1e\00\00\00n\00o\00t\00 \00i\00m\00p\00l\00e\00m\00e\00n\00t\00e\00d")
1718
(global $class-overloading/which (mut i32) (i32.const 1056))
1819
(global $~lib/rt/stub/offset (mut i32) (i32.const 0))
1920
(global $class-overloading/a (mut i32) (i32.const 0))
2021
(global $class-overloading/ia (mut i32) (i32.const 0))
2122
(global $class-overloading/ic (mut i32) (i32.const 0))
23+
(global $class-overloading/b2 (mut i32) (i32.const 0))
2224
(global $~started (mut i32) (i32.const 0))
2325
(export "_start" (func $~start))
2426
(export "memory" (memory $0))
@@ -264,7 +266,8 @@
264266
call $class-overloading/B#constructor
265267
)
266268
(func $start:class-overloading
267-
i32.const 1324
269+
(local $0 i32)
270+
i32.const 1388
268271
global.set $~lib/rt/stub/offset
269272
i32.const 0
270273
call $class-overloading/B#constructor
@@ -633,6 +636,53 @@
633636
call $~lib/builtins/abort
634637
unreachable
635638
end
639+
i32.const 14
640+
call $~lib/rt/stub/__new
641+
local.tee $0
642+
if (result i32)
643+
local.get $0
644+
else
645+
i32.const 13
646+
call $~lib/rt/stub/__new
647+
end
648+
global.set $class-overloading/b2
649+
block $__inlined_func$class-overloading/A2#foo@virtual
650+
global.get $class-overloading/b2
651+
i32.const 8
652+
i32.sub
653+
i32.load
654+
i32.const 14
655+
i32.eq
656+
if
657+
i32.const 15
658+
call $~lib/rt/stub/__new
659+
local.tee $0
660+
if (result i32)
661+
local.get $0
662+
else
663+
i32.const 16
664+
call $~lib/rt/stub/__new
665+
end
666+
i32.const 8
667+
i32.sub
668+
i32.load
669+
i32.const 15
670+
i32.eq
671+
br_if $__inlined_func$class-overloading/A2#foo@virtual
672+
i32.const 1344
673+
i32.const 1152
674+
i32.const 186
675+
i32.const 5
676+
call $~lib/builtins/abort
677+
unreachable
678+
end
679+
i32.const 1344
680+
i32.const 1152
681+
i32.const 198
682+
i32.const 5
683+
call $~lib/builtins/abort
684+
unreachable
685+
end
636686
)
637687
(func $~start
638688
global.get $~started

tests/compiler/class-overloading.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,35 @@ var ic: IC = new CC();
175175
which = "";
176176
ic.foo();
177177
assert(which == "IC");
178+
179+
// Should make stubs for functions discovered when compiling other virtual stubs
180+
class A1 {
181+
public bar(): i32 {
182+
return this.baz();
183+
// 4) discovers A1#baz
184+
}
185+
public baz(): i32 {
186+
throw new Error("not implemented");
187+
// 5) discovers B1#baz (overload)
188+
}
189+
}
190+
class B1 extends A1 {
191+
public baz(): i32 {
192+
return 3;
193+
// 6) complete
194+
}
195+
}
196+
class A2 {
197+
foo(): i32 {
198+
throw new Error("not implemented");
199+
// 2) discovers B2#foo (overload)
200+
}
201+
}
202+
class B2 extends A2 {
203+
foo(): i32 {
204+
return new B1().bar();
205+
// 3) discovers B1#bar (alias of A1#bar)
206+
}
207+
}
208+
var b2: A2 = new B2();
209+
assert(b2.foo() == 3); // 1) discovers A2#foo

tests/compiler/class-overloading.untouched.wat

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
(data (i32.const 204) "\02\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00F\00")
1717
(data (i32.const 236) "\04\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\04\00\00\00I\00B\00")
1818
(data (i32.const 268) "\04\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\04\00\00\00I\00C\00")
19+
(data (i32.const 300) "\1e\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\1e\00\00\00n\00o\00t\00 \00i\00m\00p\00l\00e\00m\00e\00n\00t\00e\00d\00")
1920
(table $0 1 funcref)
2021
(global $class-overloading/which (mut i32) (i32.const 32))
2122
(global $~lib/rt/stub/startOffset (mut i32) (i32.const 0))
@@ -25,8 +26,9 @@
2526
(global $class-overloading/c (mut i32) (i32.const 0))
2627
(global $class-overloading/ia (mut i32) (i32.const 0))
2728
(global $class-overloading/ic (mut i32) (i32.const 0))
29+
(global $class-overloading/b2 (mut i32) (i32.const 0))
2830
(global $~started (mut i32) (i32.const 0))
29-
(global $~lib/memory/__heap_base i32 (i32.const 292))
31+
(global $~lib/memory/__heap_base i32 (i32.const 352))
3032
(export "_start" (func $~start))
3133
(export "memory" (memory $0))
3234
(func $~lib/rt/stub/computeSize (param $0 i32) (result i32)
@@ -589,6 +591,41 @@
589591
end
590592
local.get $0
591593
)
594+
(func $class-overloading/A2#constructor (param $0 i32) (result i32)
595+
local.get $0
596+
i32.eqz
597+
if
598+
i32.const 0
599+
i32.const 13
600+
call $~lib/rt/stub/__new
601+
call $~lib/rt/stub/__retain
602+
local.set $0
603+
end
604+
local.get $0
605+
)
606+
(func $class-overloading/B2#constructor (param $0 i32) (result i32)
607+
local.get $0
608+
i32.eqz
609+
if
610+
i32.const 0
611+
i32.const 14
612+
call $~lib/rt/stub/__new
613+
call $~lib/rt/stub/__retain
614+
local.set $0
615+
end
616+
local.get $0
617+
call $class-overloading/A2#constructor
618+
local.set $0
619+
local.get $0
620+
)
621+
(func $class-overloading/A2#foo (param $0 i32) (result i32)
622+
i32.const 320
623+
i32.const 128
624+
i32.const 198
625+
i32.const 5
626+
call $~lib/builtins/abort
627+
unreachable
628+
)
592629
(func $start:class-overloading
593630
(local $0 i32)
594631
global.get $~lib/memory/__heap_base
@@ -1074,6 +1111,22 @@
10741111
call $~lib/builtins/abort
10751112
unreachable
10761113
end
1114+
i32.const 0
1115+
call $class-overloading/B2#constructor
1116+
global.set $class-overloading/b2
1117+
global.get $class-overloading/b2
1118+
call $class-overloading/A2#foo@virtual
1119+
i32.const 3
1120+
i32.eq
1121+
i32.eqz
1122+
if
1123+
i32.const 0
1124+
i32.const 128
1125+
i32.const 209
1126+
i32.const 1
1127+
call $~lib/builtins/abort
1128+
unreachable
1129+
end
10771130
)
10781131
(func $~start
10791132
global.get $~started
@@ -1402,4 +1455,102 @@
14021455
end
14031456
unreachable
14041457
)
1458+
(func $class-overloading/A1#constructor (param $0 i32) (result i32)
1459+
local.get $0
1460+
i32.eqz
1461+
if
1462+
i32.const 0
1463+
i32.const 16
1464+
call $~lib/rt/stub/__new
1465+
call $~lib/rt/stub/__retain
1466+
local.set $0
1467+
end
1468+
local.get $0
1469+
)
1470+
(func $class-overloading/B1#constructor (param $0 i32) (result i32)
1471+
local.get $0
1472+
i32.eqz
1473+
if
1474+
i32.const 0
1475+
i32.const 15
1476+
call $~lib/rt/stub/__new
1477+
call $~lib/rt/stub/__retain
1478+
local.set $0
1479+
end
1480+
local.get $0
1481+
call $class-overloading/A1#constructor
1482+
local.set $0
1483+
local.get $0
1484+
)
1485+
(func $class-overloading/A1#baz (param $0 i32) (result i32)
1486+
i32.const 320
1487+
i32.const 128
1488+
i32.const 186
1489+
i32.const 5
1490+
call $~lib/builtins/abort
1491+
unreachable
1492+
)
1493+
(func $class-overloading/A1#bar (param $0 i32) (result i32)
1494+
local.get $0
1495+
call $class-overloading/A1#baz@virtual
1496+
)
1497+
(func $class-overloading/B2#foo (param $0 i32) (result i32)
1498+
(local $1 i32)
1499+
(local $2 i32)
1500+
i32.const 0
1501+
call $class-overloading/B1#constructor
1502+
local.tee $1
1503+
call $class-overloading/A1#bar
1504+
local.set $2
1505+
local.get $1
1506+
call $~lib/rt/stub/__release
1507+
local.get $2
1508+
)
1509+
(func $class-overloading/A2#foo@virtual (param $0 i32) (result i32)
1510+
(local $1 i32)
1511+
block $default
1512+
block $case0
1513+
local.get $0
1514+
i32.const 8
1515+
i32.sub
1516+
i32.load
1517+
local.set $1
1518+
local.get $1
1519+
i32.const 14
1520+
i32.eq
1521+
br_if $case0
1522+
br $default
1523+
end
1524+
local.get $0
1525+
call $class-overloading/B2#foo
1526+
return
1527+
end
1528+
local.get $0
1529+
call $class-overloading/A2#foo
1530+
)
1531+
(func $class-overloading/B1#baz (param $0 i32) (result i32)
1532+
i32.const 3
1533+
)
1534+
(func $class-overloading/A1#baz@virtual (param $0 i32) (result i32)
1535+
(local $1 i32)
1536+
block $default
1537+
block $case0
1538+
local.get $0
1539+
i32.const 8
1540+
i32.sub
1541+
i32.load
1542+
local.set $1
1543+
local.get $1
1544+
i32.const 15
1545+
i32.eq
1546+
br_if $case0
1547+
br $default
1548+
end
1549+
local.get $0
1550+
call $class-overloading/B1#baz
1551+
return
1552+
end
1553+
local.get $0
1554+
call $class-overloading/A1#baz
1555+
)
14051556
)

0 commit comments

Comments
 (0)