@@ -263,6 +263,7 @@ function isdefined_nothrow(argtypes::Array{Any, 1})
263
263
(argtypes[2 ] ⊑ Symbol || argtypes[2 ] ⊑ Int) :
264
264
argtypes[2 ] ⊑ Symbol
265
265
end
266
+ isdefined_tfunc (arg1, sym, order) = (@nospecialize ; isdefined_tfunc (arg1, sym))
266
267
function isdefined_tfunc (@nospecialize (arg1), @nospecialize (sym))
267
268
if isa (arg1, Const)
268
269
a1 = typeof (arg1. val)
@@ -316,7 +317,7 @@ function isdefined_tfunc(@nospecialize(arg1), @nospecialize(sym))
316
317
end
317
318
return Bool
318
319
end
319
- add_tfunc (isdefined, 2 , 2 , isdefined_tfunc, 1 )
320
+ add_tfunc (isdefined, 2 , 3 , isdefined_tfunc, 1 )
320
321
321
322
function sizeof_nothrow (@nospecialize (x))
322
323
if isa (x, Const)
@@ -470,22 +471,26 @@ add_tfunc(arraysize, 2, 2, (@nospecialize(a), @nospecialize(d))->Int, 4)
470
471
function pointer_eltype (@nospecialize (ptr))
471
472
a = widenconst (ptr)
472
473
if a <: Ptr
473
- if isa (a,DataType) && isa (a. parameters[1 ],Type)
474
+ if isa (a, DataType) && isa (a. parameters[1 ], Type)
474
475
return a. parameters[1 ]
475
- elseif isa (a,UnionAll) && ! has_free_typevars (a)
476
+ elseif isa (a, UnionAll) && ! has_free_typevars (a)
476
477
unw = unwrap_unionall (a)
477
- if isa (unw,DataType)
478
+ if isa (unw, DataType)
478
479
return rewrap_unionall (unw. parameters[1 ], a)
479
480
end
480
481
end
481
482
end
482
483
return Any
483
484
end
484
- add_tfunc (pointerref, 3 , 3 ,
485
- function (@nospecialize (a), @nospecialize (i), @nospecialize (align))
486
- return pointer_eltype (a)
487
- end , 4 )
488
- add_tfunc (pointerset, 4 , 4 , (@nospecialize (a), @nospecialize (v), @nospecialize (i), @nospecialize (align)) -> a, 5 )
485
+ add_tfunc (pointerref, 3 , 3 , (a, i, align) -> (@nospecialize ; pointer_eltype (a)), 4 )
486
+ add_tfunc (pointerset, 4 , 4 , (a, v, i, align) -> (@nospecialize ; a), 5 )
487
+
488
+ add_tfunc (atomic_fence, 1 , 1 , (order) -> (@nospecialize ; Nothing), 4 )
489
+ add_tfunc (atomic_pointerref, 2 , 2 , (a, order) -> (@nospecialize ; pointer_eltype (a)), 4 )
490
+ add_tfunc (atomic_pointerset, 3 , 3 , (a, v, order) -> (@nospecialize ; a), 5 )
491
+ add_tfunc (atomic_pointerswap, 3 , 3 , (a, v, order) -> (@nospecialize ; pointer_eltype (a)), 5 )
492
+ add_tfunc (atomic_pointermodify, 4 , 4 , (a, op, v, order) -> (@nospecialize ; T = pointer_eltype (a); Tuple{T, T}), 5 )
493
+ add_tfunc (atomic_pointerreplace, 5 , 5 , (a, x, v, success_order, failure_order) -> (@nospecialize ; Tuple{pointer_eltype (a), Bool}), 5 )
489
494
490
495
# more accurate typeof_tfunc for vararg tuples abstract only in length
491
496
function typeof_concrete_vararg (t:: DataType )
@@ -675,14 +680,25 @@ function try_compute_fieldidx(typ::DataType, @nospecialize(field))
675
680
end
676
681
677
682
function getfield_nothrow (argtypes:: Vector{Any} )
678
- 2 <= length (argtypes) <= 3 || return false
679
- length (argtypes) == 2 && return getfield_nothrow (argtypes[1 ], argtypes[2 ], Const (true ))
680
- return getfield_nothrow (argtypes[1 ], argtypes[2 ], argtypes[3 ])
683
+ if length (argtypes) == 2
684
+ boundscheck = Bool
685
+ elseif length (argtypes) == 3
686
+ boundscheck = argtypes[3 ]
687
+ if boundscheck === Const (:not_atomic ) # TODO : this is assuming not atomic
688
+ boundscheck = Bool
689
+ end
690
+ elseif length (argtypes) == 4
691
+ boundscheck = argtypes[4 ]
692
+ else
693
+ return false
694
+ end
695
+ widenconst (boundscheck) != = Bool && return false
696
+ bounds_check_disabled = isa (boundscheck, Const) && boundscheck. val === false
697
+ return getfield_nothrow (argtypes[1 ], argtypes[2 ], ! bounds_check_disabled)
681
698
end
682
- function getfield_nothrow (@nospecialize (s00), @nospecialize (name), @nospecialize (inbounds))
683
- bounds_check_disabled = isa (inbounds, Const) && inbounds. val === false
684
- # If we don't have invounds and don't know the field, don't even bother
685
- if ! bounds_check_disabled
699
+ function getfield_nothrow (@nospecialize (s00), @nospecialize (name), boundscheck:: Bool )
700
+ # If we don't have boundscheck and don't know the field, don't even bother
701
+ if boundscheck
686
702
isa (name, Const) || return false
687
703
end
688
704
@@ -700,7 +716,7 @@ function getfield_nothrow(@nospecialize(s00), @nospecialize(name), @nospecialize
700
716
end
701
717
return isdefined (sv, name. val)
702
718
end
703
- if bounds_check_disabled && ! isa (sv, Module)
719
+ if ! boundscheck && ! isa (sv, Module)
704
720
# If bounds checking is disabled and all fields are assigned,
705
721
# we may assume that we don't throw
706
722
for i = 1 : fieldcount (typeof (sv))
@@ -714,14 +730,15 @@ function getfield_nothrow(@nospecialize(s00), @nospecialize(name), @nospecialize
714
730
s0 = widenconst (s00)
715
731
s = unwrap_unionall (s0)
716
732
if isa (s, Union)
717
- return getfield_nothrow (rewrap (s. a, s00), name, inbounds ) &&
718
- getfield_nothrow (rewrap (s. b, s00), name, inbounds )
733
+ return getfield_nothrow (rewrap (s. a, s00), name, boundscheck ) &&
734
+ getfield_nothrow (rewrap (s. b, s00), name, boundscheck )
719
735
elseif isa (s, DataType)
720
736
# Can't say anything about abstract types
721
737
s. name. abstract && return false
738
+ s. name. atomicfields == C_NULL || return false # TODO : currently we're only testing for ordering == :not_atomic
722
739
# If all fields are always initialized, and bounds check is disabled, we can assume
723
740
# we don't throw
724
- if bounds_check_disabled && ! isvatuple (s) && s. name != = NamedTuple. body. body. name && fieldcount (s) == s. ninitialized
741
+ if ! boundscheck && ! isvatuple (s) && s. name != = NamedTuple. body. body. name && fieldcount (s) == s. ninitialized
725
742
return true
726
743
end
727
744
# Else we need to know what the field is
@@ -736,8 +753,8 @@ function getfield_nothrow(@nospecialize(s00), @nospecialize(name), @nospecialize
736
753
return false
737
754
end
738
755
739
- getfield_tfunc (@nospecialize ( s00), @nospecialize ( name), @nospecialize (inbounds)) =
740
- getfield_tfunc (s00, name)
756
+ getfield_tfunc (s00, name, boundscheck_or_order) = ( @nospecialize ; getfield_tfunc (s00, name))
757
+ getfield_tfunc (s00, name, order, boundscheck) = ( @nospecialize ; getfield_tfunc (s00, name) )
741
758
function getfield_tfunc (@nospecialize (s00), @nospecialize (name))
742
759
s = unwrap_unionall (s00)
743
760
if isa (s, Union)
@@ -892,10 +909,25 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
892
909
end
893
910
return rewrap_unionall (R, s00)
894
911
end
895
- add_tfunc (getfield, 2 , 3 , getfield_tfunc, 1 )
896
- add_tfunc (setfield!, 3 , 3 , (@nospecialize (o), @nospecialize (f), @nospecialize (v)) -> v, 3 )
897
- fieldtype_tfunc (@nospecialize (s0), @nospecialize (name), @nospecialize (inbounds)) =
898
- fieldtype_tfunc (s0, name)
912
+
913
+ setfield!_tfunc (o, f, v, order) = (@nospecialize ; v)
914
+ setfield!_tfunc (o, f, v) = (@nospecialize ; v)
915
+
916
+ swapfield!_tfunc (o, f, v, order) = (@nospecialize ; getfield_tfunc (o, f))
917
+ swapfield!_tfunc (o, f, v) = (@nospecialize ; getfield_tfunc (o, f))
918
+ modifyfield!_tfunc (o, f, op, v, order) = (@nospecialize ; T = getfield_tfunc (o, f); T === Bottom ? T : Tuple{T, T})
919
+ modifyfield!_tfunc (o, f, op, v) = (@nospecialize ; T = getfield_tfunc (o, f); T === Bottom ? T : Tuple{T, T}) # TODO : also model op(o.f, v) call
920
+ replacefield!_tfunc (o, f, x, v, success_order, failure_order) = (@nospecialize ; replacefield!_tfunc (o, f, x, v))
921
+ replacefield!_tfunc (o, f, x, v, success_order) = (@nospecialize ; replacefield!_tfunc (o, f, x, v))
922
+ replacefield!_tfunc (o, f, x, v) = (@nospecialize ; T = getfield_tfunc (o, f); T === Bottom ? T : Tuple{widenconst (T), Bool})
923
+ # we could use tuple_tfunc instead of widenconst, but `o` is mutable, so that is unlikely to be beneficial
924
+
925
+ add_tfunc (getfield, 2 , 4 , getfield_tfunc, 1 )
926
+ add_tfunc (setfield!, 3 , 4 , setfield!_tfunc, 3 )
927
+
928
+ add_tfunc (swapfield!, 3 , 4 , swapfield!_tfunc, 3 )
929
+ add_tfunc (modifyfield!, 4 , 5 , modifyfield!_tfunc, 3 )
930
+ add_tfunc (replacefield!, 4 , 6 , replacefield!_tfunc, 3 )
899
931
900
932
function fieldtype_nothrow (@nospecialize (s0), @nospecialize (name))
901
933
s0 === Bottom && return true # unreachable
@@ -954,6 +986,7 @@ function _fieldtype_nothrow(@nospecialize(s), exact::Bool, name::Const)
954
986
return true
955
987
end
956
988
989
+ fieldtype_tfunc (s0, name, boundscheck) = (@nospecialize ; fieldtype_tfunc (s0, name))
957
990
function fieldtype_tfunc (@nospecialize (s0), @nospecialize (name))
958
991
if s0 === Bottom
959
992
return Bottom
0 commit comments