@@ -1664,7 +1664,9 @@ and OpHasEffect g m op =
1664
1664
| TOp.ExnFieldGet ( ecref, n) -> isExnFieldMutable ecref n
1665
1665
| TOp.RefAddrGet _ -> false
1666
1666
| TOp.AnonRecdGet _ -> true // conservative
1667
- | TOp.ValFieldGet rfref -> rfref.RecdField.IsMutable || ( TryFindTyconRefBoolAttribute g range0 g.attrib_ AllowNullLiteralAttribute rfref.TyconRef = Some true )
1667
+ | TOp.ValFieldGet rfref ->
1668
+ rfref.RecdField.IsMutable
1669
+ || ( TryFindTyconRefBoolAttribute g range0 g.attrib_ AllowNullLiteralAttribute rfref.TyconRef = Some true )
1668
1670
| TOp.ValFieldGetAddr ( rfref, _ readonly) -> rfref.RecdField.IsMutable
1669
1671
| TOp.UnionCaseFieldGetAddr _ -> false // union case fields are immutable
1670
1672
| TOp.LValueOp ( LAddrOf _, _) -> false // addresses of values are always constants
@@ -3167,7 +3169,7 @@ and CanDevirtualizeApplication cenv v vref ty args =
3167
3169
&& not ( isUnitTy g ty)
3168
3170
&& isAppTy g ty
3169
3171
// Exclusion: Some unions have null as representations
3170
- && not ( IsUnionTypeWithNullAsTrueValue g ( fst( StripToNominalTyconRef cenv ty)) .Deref)
3172
+ && not ( IsUnionTypeWithNullAsTrueValue g ( fst( StripToNominalTyconRef cenv ty)) .Deref)
3171
3173
// If we de-virtualize an operation on structs then we have to take the address of the object argument
3172
3174
// Hence we have to actually have the object argument available to us,
3173
3175
&& ( not ( isStructTy g ty) || not ( isNil args))
@@ -3189,9 +3191,13 @@ and TakeAddressOfStructArgumentIfNeeded cenv (vref: ValRef) ty args m =
3189
3191
else
3190
3192
id, args
3191
3193
3192
- and DevirtualizeApplication cenv env ( vref : ValRef ) ty tyargs args m =
3194
+ and DevirtualizeApplication cenv env ( vref : ValRef ) ty tyargs args m nullHandlerOpt =
3193
3195
let g = cenv.g
3194
- let wrap , args = TakeAddressOfStructArgumentIfNeeded cenv vref ty args m
3196
+ let wrap , args =
3197
+ match nullHandlerOpt with
3198
+ | Some nullHandler when g.checkNullness && TypeNullIsExtraValueNew g vref.Range ty ->
3199
+ nullHandler g m, args
3200
+ | _ -> TakeAddressOfStructArgumentIfNeeded cenv vref ty args m
3195
3201
let transformedExpr = wrap ( MakeApplicationAndBetaReduce g ( exprForValRef m vref, vref.Type, ( if isNil tyargs then [] else [ tyargs]), args, m))
3196
3202
OptimizeExpr cenv env transformedExpr
3197
3203
@@ -3212,8 +3218,10 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3212
3218
| Expr.Val ( v, _, _), [ ty], _ when CanDevirtualizeApplication cenv v g.generic_ comparison_ inner_ vref ty args ->
3213
3219
3214
3220
let tcref , tyargs = StripToNominalTyconRef cenv ty
3215
- match tcref.GeneratedCompareToValues with
3216
- | Some (_, vref) -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3221
+ match tcref.GeneratedCompareToValues, args with
3222
+ | Some (_, vref), [ x; y] ->
3223
+ let nullHandler g m = AugmentTypeDefinitions.mkBindNullComparison g m x y
3224
+ Some ( DevirtualizeApplication cenv env vref ty tyargs args m ( Some nullHandler))
3217
3225
| _ -> None
3218
3226
3219
3227
| Expr.Val ( v, _, _), [ ty], _ when CanDevirtualizeApplication cenv v g.generic_ comparison_ withc_ inner_ vref ty args ->
@@ -3225,7 +3233,8 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3225
3233
// arg list, and create a tuple of y & comp
3226
3234
// push the comparer to the end and box the argument
3227
3235
let args2 = [ x; mkRefTupledNoTypes g m [ mkCoerceExpr( y, g.obj_ ty_ ambivalent, m, ty) ; comp]]
3228
- Some ( DevirtualizeApplication cenv env vref ty tyargs args2 m)
3236
+ let nullHandler g m = AugmentTypeDefinitions.mkBindNullComparison g m x y
3237
+ Some ( DevirtualizeApplication cenv env vref ty tyargs args2 m ( Some nullHandler))
3229
3238
| _ -> None
3230
3239
3231
3240
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityIntrinsic when type is known
@@ -3235,8 +3244,10 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3235
3244
| Expr.Val ( v, _, _), [ ty], _ when CanDevirtualizeApplication cenv v g.generic_ equality_ er_ inner_ vref ty args ->
3236
3245
3237
3246
let tcref , tyargs = StripToNominalTyconRef cenv ty
3238
- match tcref.GeneratedHashAndEqualsValues with
3239
- | Some (_, vref) -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3247
+ match tcref.GeneratedHashAndEqualsValues, args with
3248
+ | Some (_, vref),[ x; y] ->
3249
+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3250
+ Some ( DevirtualizeApplication cenv env vref ty tyargs args m ( Some nullHandler))
3240
3251
| _ -> None
3241
3252
3242
3253
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityWithComparerIntrinsic
@@ -3246,11 +3257,13 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3246
3257
| Some (_, _, _, Some withcEqualsExactVal), [ comp; x; y] ->
3247
3258
// push the comparer to the end
3248
3259
let args2 = [ x; mkRefTupledNoTypes g m [ y; comp]]
3249
- Some ( DevirtualizeApplication cenv env withcEqualsExactVal ty tyargs args2 m)
3260
+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3261
+ Some ( DevirtualizeApplication cenv env withcEqualsExactVal ty tyargs args2 m ( Some nullHandler))
3250
3262
| Some (_, _, withcEqualsVal, _ ), [ comp; x; y] ->
3251
3263
// push the comparer to the end and box the argument
3252
3264
let args2 = [ x; mkRefTupledNoTypes g m [ mkCoerceExpr( y, g.obj_ ty_ ambivalent, m, ty) ; comp]]
3253
- Some ( DevirtualizeApplication cenv env withcEqualsVal ty tyargs args2 m)
3265
+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3266
+ Some ( DevirtualizeApplication cenv env withcEqualsVal ty tyargs args2 m ( Some nullHandler))
3254
3267
| _ -> None
3255
3268
3256
3269
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityIntrinsic
@@ -3259,20 +3272,23 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3259
3272
match tcref.GeneratedHashAndEqualsWithComparerValues, args with
3260
3273
| Some (_, _, _, Some withcEqualsExactVal), [ x; y] ->
3261
3274
let args2 = [ x; mkRefTupledNoTypes g m [ y; ( mkCallGetGenericPEREqualityComparer g m)]]
3262
- Some ( DevirtualizeApplication cenv env withcEqualsExactVal ty tyargs args2 m)
3275
+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3276
+ Some ( DevirtualizeApplication cenv env withcEqualsExactVal ty tyargs args2 m ( Some nullHandler))
3263
3277
| Some (_, _, withcEqualsVal, _), [ x; y] ->
3264
3278
let equalsExactOpt =
3265
3279
tcref.MembersOfFSharpTyconByName.TryFind( " Equals" )
3266
3280
|> Option.map ( List.where ( fun x -> x.IsCompilerGenerated))
3267
3281
|> Option.bind List.tryExactlyOne
3268
3282
3283
+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3284
+
3269
3285
match equalsExactOpt with
3270
3286
| Some equalsExact ->
3271
3287
let args2 = [ x; mkRefTupledNoTypes g m [ y; ( mkCallGetGenericPEREqualityComparer g m)]]
3272
- Some ( DevirtualizeApplication cenv env equalsExact ty tyargs args2 m)
3288
+ Some ( DevirtualizeApplication cenv env equalsExact ty tyargs args2 m ( Some nullHandler ) )
3273
3289
| None ->
3274
3290
let args2 = [ x; mkRefTupledNoTypes g m [ mkCoerceExpr( y, g.obj_ ty_ ambivalent, m, ty); ( mkCallGetGenericPEREqualityComparer g m)]]
3275
- Some ( DevirtualizeApplication cenv env withcEqualsVal ty tyargs args2 m)
3291
+ Some ( DevirtualizeApplication cenv env withcEqualsVal ty tyargs args2 m ( Some nullHandler ) )
3276
3292
| _ -> None
3277
3293
3278
3294
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericHashIntrinsic
@@ -3281,7 +3297,8 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3281
3297
match tcref.GeneratedHashAndEqualsWithComparerValues, args with
3282
3298
| Some (_, withcGetHashCodeVal, _, _), [ x] ->
3283
3299
let args2 = [ x; mkCallGetGenericEREqualityComparer g m]
3284
- Some ( DevirtualizeApplication cenv env withcGetHashCodeVal ty tyargs args2 m)
3300
+ let nullHandler g m = AugmentTypeDefinitions.mkBindNullHash g m x
3301
+ Some ( DevirtualizeApplication cenv env withcGetHashCodeVal ty tyargs args2 m ( Some nullHandler))
3285
3302
| _ -> None
3286
3303
3287
3304
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericHashWithComparerIntrinsic
@@ -3290,7 +3307,8 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3290
3307
match tcref.GeneratedHashAndEqualsWithComparerValues, args with
3291
3308
| Some (_, withcGetHashCodeVal, _, _), [ comp; x] ->
3292
3309
let args2 = [ x; comp]
3293
- Some ( DevirtualizeApplication cenv env withcGetHashCodeVal ty tyargs args2 m)
3310
+ let nullHandler g m = AugmentTypeDefinitions.mkBindNullHash g m x
3311
+ Some ( DevirtualizeApplication cenv env withcGetHashCodeVal ty tyargs args2 m ( Some nullHandler))
3294
3312
| _ -> None
3295
3313
3296
3314
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericComparisonWithComparerIntrinsic for tuple types
@@ -3304,7 +3322,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3304
3322
| 5 -> Some g.generic_ compare_ withc_ tuple5_ vref
3305
3323
| _ -> None
3306
3324
match vref with
3307
- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericComparer g m :: args) m)
3325
+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericComparer g m :: args) m None )
3308
3326
| None -> None
3309
3327
3310
3328
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericHashWithComparerIntrinsic for tuple types
@@ -3318,7 +3336,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3318
3336
| 5 -> Some g.generic_ hash_ withc_ tuple5_ vref
3319
3337
| _ -> None
3320
3338
match vref with
3321
- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericEREqualityComparer g m :: args) m)
3339
+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericEREqualityComparer g m :: args) m None )
3322
3340
| None -> None
3323
3341
3324
3342
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityIntrinsic for tuple types
@@ -3334,7 +3352,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3334
3352
| 5 -> Some g.generic_ equals_ withc_ tuple5_ vref
3335
3353
| _ -> None
3336
3354
match vref with
3337
- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericPEREqualityComparer g m :: args) m)
3355
+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericPEREqualityComparer g m :: args) m None )
3338
3356
| None -> None
3339
3357
3340
3358
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericComparisonWithComparerIntrinsic for tuple types
@@ -3348,7 +3366,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3348
3366
| 5 -> Some g.generic_ compare_ withc_ tuple5_ vref
3349
3367
| _ -> None
3350
3368
match vref with
3351
- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3369
+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m None )
3352
3370
| None -> None
3353
3371
3354
3372
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericHashWithComparerIntrinsic for tuple types
@@ -3362,7 +3380,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3362
3380
| 5 -> Some g.generic_ hash_ withc_ tuple5_ vref
3363
3381
| _ -> None
3364
3382
match vref with
3365
- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3383
+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m None )
3366
3384
| None -> None
3367
3385
3368
3386
// Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityWithComparerIntrinsic for tuple types
@@ -3376,7 +3394,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3376
3394
| 5 -> Some g.generic_ equals_ withc_ tuple5_ vref
3377
3395
| _ -> None
3378
3396
match vref with
3379
- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3397
+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m None )
3380
3398
| None -> None
3381
3399
3382
3400
// Calls to LanguagePrimitives.IntrinsicFunctions.UnboxGeneric can be optimized to calls to UnboxFast when we know that the
@@ -3385,15 +3403,15 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
3385
3403
| Expr.Val ( v, _, _), [ ty], _ when valRefEq g v g.unbox_ vref &&
3386
3404
canUseUnboxFast g m ty ->
3387
3405
3388
- Some( DevirtualizeApplication cenv env g.unbox_ fast_ vref ty tyargs args m)
3406
+ Some( DevirtualizeApplication cenv env g.unbox_ fast_ vref ty tyargs args m None )
3389
3407
3390
3408
// Calls to LanguagePrimitives.IntrinsicFunctions.TypeTestGeneric can be optimized to calls to TypeTestFast when we know that the
3391
3409
// target type isn't 'NullNotTrueValue', i.e. that the target type is not an F# union, record etc.
3392
3410
// Note TypeTestFast is just the .NET IL 'isinst' instruction followed by a non-null comparison
3393
3411
| Expr.Val ( v, _, _), [ ty], _ when valRefEq g v g.istype_ vref &&
3394
3412
canUseTypeTestFast g ty ->
3395
3413
3396
- Some( DevirtualizeApplication cenv env g.istype_ fast_ vref ty tyargs args m)
3414
+ Some( DevirtualizeApplication cenv env g.istype_ fast_ vref ty tyargs args m None )
3397
3415
3398
3416
// Don't fiddle with 'methodhandleof' calls - just remake the application
3399
3417
| Expr.Val ( vref, _, _), _, _ when valRefEq g vref g.methodhandleof_ vref ->
0 commit comments