Skip to content

Commit df3d29c

Browse files
authored
fix: Handle nulls in runtime upcast checks (#2042)
1 parent 115c820 commit df3d29c

File tree

3 files changed

+127
-98
lines changed

3 files changed

+127
-98
lines changed

src/compiler.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10532,14 +10532,31 @@ export class Compiler extends DiagnosticEmitter {
1053210532
var temp = flow.getTempLocal(type);
1053310533
var instanceofInstance = this.program.instanceofInstance;
1053410534
assert(this.compileFunction(instanceofInstance));
10535-
expr = module.if(
10536-
module.call(instanceofInstance.internalName, [
10535+
if (!toType.isNullableReference || flow.isNonnull(expr, type)) {
10536+
// Simplify if the value cannot be `null`. If toType is non-nullable, a
10537+
// null-check would have been emitted separately so is not necessary here.
10538+
expr = module.if(
10539+
module.call(instanceofInstance.internalName, [
10540+
module.local_tee(temp.index, expr, type.isManaged),
10541+
module.i32(toType.classReference!.id)
10542+
], TypeRef.I32),
10543+
module.local_get(temp.index, type.toRef()),
10544+
this.makeStaticAbort(this.ensureStaticString("unexpected upcast"), reportNode) // TODO: throw
10545+
);
10546+
} else {
10547+
expr = module.if(
1053710548
module.local_tee(temp.index, expr, type.isManaged),
10538-
module.i32(toType.classReference!.id)
10539-
], TypeRef.I32),
10540-
module.local_get(temp.index, type.toRef()),
10541-
this.makeStaticAbort(this.ensureStaticString("unexpected upcast"), reportNode) // TODO: throw
10542-
);
10549+
module.if(
10550+
module.call(instanceofInstance.internalName, [
10551+
module.local_get(temp.index, type.toRef()),
10552+
module.i32(toType.classReference!.id)
10553+
], TypeRef.I32),
10554+
module.local_get(temp.index, type.toRef()),
10555+
this.makeStaticAbort(this.ensureStaticString("unexpected upcast"), reportNode) // TODO: throw
10556+
),
10557+
module.usize(0)
10558+
);
10559+
}
1054310560
flow.freeTempLocal(temp);
1054410561
this.currentType = toType;
1054510562
return expr;

tests/compiler/managed-cast.optimized.wat

Lines changed: 90 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,17 +1468,17 @@
14681468
i32.const 1344
14691469
global.set $~lib/rt/itcms/fromSpace
14701470
call $managed-cast/Cat#constructor
1471-
local.set $1
1471+
local.set $0
14721472
global.get $~lib/memory/__stack_pointer
1473-
local.get $1
1473+
local.get $0
14741474
i32.store
14751475
call $managed-cast/Cat#constructor
1476-
local.set $1
1476+
local.set $0
14771477
global.get $~lib/memory/__stack_pointer
1478-
local.tee $0
1479-
local.get $1
1480-
i32.store
1478+
local.tee $1
14811479
local.get $0
1480+
i32.store
1481+
local.get $1
14821482
i32.const 4
14831483
i32.sub
14841484
global.set $~lib/memory/__stack_pointer
@@ -1489,7 +1489,7 @@
14891489
global.get $~lib/memory/__stack_pointer
14901490
i32.const 0
14911491
i32.store
1492-
local.get $1
1492+
local.get $0
14931493
i32.eqz
14941494
if
14951495
i32.const 1456
@@ -1500,30 +1500,30 @@
15001500
unreachable
15011501
end
15021502
global.get $~lib/memory/__stack_pointer
1503-
local.tee $0
1504-
local.get $1
1505-
i32.store
1503+
local.tee $1
15061504
local.get $0
1505+
i32.store
1506+
local.get $1
15071507
i32.const 4
15081508
i32.add
15091509
global.set $~lib/memory/__stack_pointer
15101510
call $managed-cast/Cat#constructor
1511-
local.set $1
1511+
local.set $0
15121512
global.get $~lib/memory/__stack_pointer
1513-
local.get $1
1513+
local.get $0
15141514
i32.store
15151515
call $managed-cast/Cat#constructor
1516-
local.set $1
1516+
local.set $0
15171517
global.get $~lib/memory/__stack_pointer
1518-
local.get $1
1518+
local.get $0
15191519
i32.store
15201520
call $managed-cast/Cat#constructor
1521-
local.set $1
1521+
local.set $0
15221522
global.get $~lib/memory/__stack_pointer
1523-
local.tee $0
1524-
local.get $1
1525-
i32.store
1523+
local.tee $1
15261524
local.get $0
1525+
i32.store
1526+
local.get $1
15271527
i32.const 4
15281528
i32.sub
15291529
global.set $~lib/memory/__stack_pointer
@@ -1535,29 +1535,29 @@
15351535
i32.const 0
15361536
i32.store
15371537
block $__inlined_func$~lib/rt/__instanceof (result i32)
1538-
local.get $1
1538+
local.get $0
15391539
i32.const 20
15401540
i32.sub
15411541
i32.load offset=12
1542-
local.tee $0
1542+
local.tee $1
15431543
i32.const 1632
15441544
i32.load
15451545
i32.le_u
15461546
if
15471547
loop $do-continue|0
15481548
i32.const 1
1549-
local.get $0
1549+
local.get $1
15501550
i32.const 3
15511551
i32.eq
15521552
br_if $__inlined_func$~lib/rt/__instanceof
15531553
drop
1554-
local.get $0
1554+
local.get $1
15551555
i32.const 3
15561556
i32.shl
15571557
i32.const 1636
15581558
i32.add
15591559
i32.load offset=4
1560-
local.tee $0
1560+
local.tee $1
15611561
br_if $do-continue|0
15621562
end
15631563
end
@@ -1573,20 +1573,20 @@
15731573
unreachable
15741574
end
15751575
global.get $~lib/memory/__stack_pointer
1576-
local.tee $0
1577-
local.get $1
1578-
i32.store
1576+
local.tee $1
15791577
local.get $0
1578+
i32.store
1579+
local.get $1
15801580
i32.const 4
15811581
i32.add
15821582
global.set $~lib/memory/__stack_pointer
15831583
call $managed-cast/Cat#constructor
1584-
local.set $1
1584+
local.set $0
15851585
global.get $~lib/memory/__stack_pointer
1586-
local.tee $0
1587-
local.get $1
1588-
i32.store
1586+
local.tee $1
15891587
local.get $0
1588+
i32.store
1589+
local.get $1
15901590
i32.const 8
15911591
i32.sub
15921592
global.set $~lib/memory/__stack_pointer
@@ -1595,10 +1595,10 @@
15951595
i32.lt_s
15961596
br_if $folding-inner0
15971597
global.get $~lib/memory/__stack_pointer
1598-
local.tee $0
1598+
local.tee $1
15991599
i64.const 0
16001600
i64.store
1601-
local.get $1
1601+
local.get $0
16021602
i32.eqz
16031603
if
16041604
i32.const 1456
@@ -1608,11 +1608,12 @@
16081608
call $~lib/builtins/abort
16091609
unreachable
16101610
end
1611-
local.get $0
16121611
local.get $1
1612+
local.get $0
1613+
local.tee $1
16131614
i32.store offset=4
16141615
block $__inlined_func$~lib/rt/__instanceof11 (result i32)
1615-
local.get $1
1616+
local.get $0
16161617
i32.const 20
16171618
i32.sub
16181619
i32.load offset=12
@@ -1658,12 +1659,12 @@
16581659
i32.add
16591660
global.set $~lib/memory/__stack_pointer
16601661
call $managed-cast/Cat#constructor
1661-
local.set $1
1662+
local.set $0
16621663
global.get $~lib/memory/__stack_pointer
1663-
local.tee $0
1664-
local.get $1
1665-
i32.store
1664+
local.tee $1
16661665
local.get $0
1666+
i32.store
1667+
local.get $1
16671668
i32.const 4
16681669
i32.sub
16691670
global.set $~lib/memory/__stack_pointer
@@ -1676,29 +1677,29 @@
16761677
i32.const 0
16771678
i32.store
16781679
block $__inlined_func$~lib/rt/__instanceof14 (result i32)
1679-
local.get $1
1680+
local.get $0
16801681
i32.const 20
16811682
i32.sub
16821683
i32.load offset=12
1683-
local.tee $0
1684+
local.tee $1
16841685
i32.const 1632
16851686
i32.load
16861687
i32.le_u
16871688
if
16881689
loop $do-continue|015
16891690
i32.const 1
1690-
local.get $0
1691+
local.get $1
16911692
i32.const 3
16921693
i32.eq
16931694
br_if $__inlined_func$~lib/rt/__instanceof14
16941695
drop
1695-
local.get $0
1696+
local.get $1
16961697
i32.const 3
16971698
i32.shl
16981699
i32.const 1636
16991700
i32.add
17001701
i32.load offset=4
1701-
local.tee $0
1702+
local.tee $1
17021703
br_if $do-continue|015
17031704
end
17041705
end
@@ -1714,19 +1715,19 @@
17141715
unreachable
17151716
end
17161717
local.get $2
1717-
local.get $1
1718+
local.get $0
17181719
i32.store
17191720
global.get $~lib/memory/__stack_pointer
17201721
i32.const 4
17211722
i32.add
17221723
global.set $~lib/memory/__stack_pointer
17231724
call $managed-cast/Cat#constructor
1724-
local.set $1
1725+
local.set $0
17251726
global.get $~lib/memory/__stack_pointer
1726-
local.tee $0
1727-
local.get $1
1728-
i32.store
1727+
local.tee $1
17291728
local.get $0
1729+
i32.store
1730+
local.get $1
17301731
i32.const 4
17311732
i32.sub
17321733
global.set $~lib/memory/__stack_pointer
@@ -1738,46 +1739,52 @@
17381739
local.tee $2
17391740
i32.const 0
17401741
i32.store
1741-
block $__inlined_func$~lib/rt/__instanceof17 (result i32)
1742-
local.get $1
1743-
i32.const 20
1744-
i32.sub
1745-
i32.load offset=12
1746-
local.tee $0
1747-
i32.const 1632
1748-
i32.load
1749-
i32.le_u
1750-
if
1751-
loop $do-continue|018
1752-
i32.const 1
1753-
local.get $0
1754-
i32.const 3
1755-
i32.eq
1756-
br_if $__inlined_func$~lib/rt/__instanceof17
1757-
drop
1758-
local.get $0
1759-
i32.const 3
1760-
i32.shl
1761-
i32.const 1636
1762-
i32.add
1763-
i32.load offset=4
1764-
local.tee $0
1765-
br_if $do-continue|018
1742+
local.get $0
1743+
if
1744+
block $__inlined_func$~lib/rt/__instanceof17 (result i32)
1745+
local.get $0
1746+
i32.const 20
1747+
i32.sub
1748+
i32.load offset=12
1749+
local.tee $1
1750+
i32.const 1632
1751+
i32.load
1752+
i32.le_u
1753+
if
1754+
loop $do-continue|018
1755+
i32.const 1
1756+
local.get $1
1757+
i32.const 3
1758+
i32.eq
1759+
br_if $__inlined_func$~lib/rt/__instanceof17
1760+
drop
1761+
local.get $1
1762+
i32.const 3
1763+
i32.shl
1764+
i32.const 1636
1765+
i32.add
1766+
i32.load offset=4
1767+
local.tee $1
1768+
br_if $do-continue|018
1769+
end
17661770
end
1771+
i32.const 0
17671772
end
1773+
i32.eqz
1774+
if
1775+
i32.const 1584
1776+
i32.const 1520
1777+
i32.const 47
1778+
i32.const 30
1779+
call $~lib/builtins/abort
1780+
unreachable
1781+
end
1782+
else
17681783
i32.const 0
1769-
end
1770-
i32.eqz
1771-
if
1772-
i32.const 1584
1773-
i32.const 1520
1774-
i32.const 47
1775-
i32.const 30
1776-
call $~lib/builtins/abort
1777-
unreachable
1784+
local.set $0
17781785
end
17791786
local.get $2
1780-
local.get $1
1787+
local.get $0
17811788
i32.store
17821789
global.get $~lib/memory/__stack_pointer
17831790
i32.const 4

0 commit comments

Comments
 (0)