@@ -1040,6 +1040,13 @@ private class FunctionEmitter private (
1040
1040
* not need to store the receiver in a local at all.
1041
1041
* For the case with the args, it does not hurt either way. We could
1042
1042
* move it out, but that would make for a less consistent codegen.
1043
+ *
1044
+ * Loading the arguments and storing them in locas inside the block
1045
+ * only works if their type is defaultable. Currently, for instance
1046
+ * methods, parameter types are always defaultable, so this is fine.
1047
+ * We may need to revisit this strategy if that invariant changes.
1048
+ * If we do, it may be better to use different code paths for the
1049
+ * no-args case and the with-args case. See #5165 for more context.
1043
1050
*/
1044
1051
val argsLocals = fb.block(watpe.RefType .any) { labelNotOurObject =>
1045
1052
// Load receiver and arguments and store them in temporary variables
@@ -3623,6 +3630,11 @@ private class FunctionEmitter private (
3623
3630
* we cannot use the stack for the `try_table` itself: each label has a
3624
3631
* dedicated local for its result if it comes from such a crossing `return`.
3625
3632
*
3633
+ * Those locals must have defaultable types, because they are read outside of
3634
+ * the block where they are first ininitialized. If their natural type is not
3635
+ * defaultable, we make it defaultable, and cast away nullability when we
3636
+ * read them back. See #5165.
3637
+ *
3626
3638
* Two more complications:
3627
3639
*
3628
3640
* - If the `finally` block itself contains another `try..finally`, they may
@@ -3850,7 +3862,7 @@ private class FunctionEmitter private (
3850
3862
_crossInfo.getOrElse {
3851
3863
val destinationTag = allocateDestinationTag()
3852
3864
val resultTypes = transformResultType(expectedType)
3853
- val resultLocals = resultTypes.map(addSyntheticLocal(_ ))
3865
+ val resultLocals = resultTypes.map(tpe => addSyntheticLocal(tpe.toDefaultableType ))
3854
3866
val crossLabel = fb.genLabel()
3855
3867
val info = CrossInfo (destinationTag, resultLocals, crossLabel)
3856
3868
_crossInfo = Some (info)
@@ -3941,8 +3953,11 @@ private class FunctionEmitter private (
3941
3953
// Add the `br`, `end` and `local.get` at the current position, as usual
3942
3954
fb += wa.Br (entry.regularWasmLabel)
3943
3955
fb += wa.End
3944
- for (local <- resultLocals)
3956
+ for (( local, origType) <- resultLocals.zip(ty)) {
3945
3957
fb += wa.LocalGet (local)
3958
+ if (! origType.isDefaultable)
3959
+ fb += wa.RefAsNonNull
3960
+ }
3946
3961
}
3947
3962
3948
3963
fb += wa.End
@@ -3959,7 +3974,7 @@ private class FunctionEmitter private (
3959
3974
val entry = new TryFinallyEntry (currentUnwindingStackDepth)
3960
3975
3961
3976
val resultType = transformResultType(expectedType)
3962
- val resultLocals = resultType.map(addSyntheticLocal(_ ))
3977
+ val resultLocals = resultType.map(tpe => addSyntheticLocal(tpe.toDefaultableType ))
3963
3978
3964
3979
markPosition(tree)
3965
3980
@@ -4074,8 +4089,11 @@ private class FunctionEmitter private (
4074
4089
} // end block $done
4075
4090
4076
4091
// reload the result onto the stack
4077
- for (resultLocal <- resultLocals)
4092
+ for (( resultLocal, origType) <- resultLocals.zip(resultType)) {
4078
4093
fb += wa.LocalGet (resultLocal)
4094
+ if (! origType.isDefaultable)
4095
+ fb += wa.RefAsNonNull
4096
+ }
4079
4097
4080
4098
if (expectedType == NothingType )
4081
4099
fb += wa.Unreachable
0 commit comments