@@ -516,7 +516,7 @@ The following `setting`s are supported.
516
516
- `:foldable`
517
517
- `:removable`
518
518
- `:total`
519
-
519
+ - `:gc_safe`
520
520
# Extended help
521
521
522
522
---
@@ -750,6 +750,13 @@ the following other `setting`s:
750
750
number of effect overrides apply to a set of functions, a custom macro is
751
751
recommended over the use of `:total`.
752
752
753
+ ---
754
+ ## `:gc_safe`
755
+
756
+ This `setting` can only be applied to `@ccall` expressions. It asserts that the
757
+ `@ccall` is safe to execute concurrently with the garbage collector. This means that it must not
758
+ call into the julia runtime.
759
+
753
760
---
754
761
## Negated effects
755
762
@@ -759,12 +766,13 @@ the call is generally total, it may however throw.
759
766
"""
760
767
macro assume_effects (args... )
761
768
lastex = args[end ]
762
- override = compute_assumed_settings (args[begin : end - 1 ])
769
+ override, gc_safe = compute_assumed_settings (args[begin : end - 1 ])
763
770
if is_function_def (unwrap_macrocalls (lastex))
764
771
return esc (pushmeta! (lastex:: Expr , form_purity_expr (override)))
765
772
elseif isexpr (lastex, :macrocall ) && lastex. args[1 ] === Symbol (" @ccall" )
766
773
lastex. args[1 ] = GlobalRef (Base, Symbol (" @ccall_effects" ))
767
774
insert! (lastex. args, 3 , encode_effects_override (override))
775
+ insert! (lastex. args, 4 , gc_safe)
768
776
return esc (lastex)
769
777
end
770
778
override′ = compute_assumed_setting (override, lastex)
@@ -783,12 +791,19 @@ end
783
791
784
792
function compute_assumed_settings (settings)
785
793
override = EffectsOverride ()
794
+ gc_safe = false
786
795
for setting in settings
796
+ # This way of parsing is slightly annoying, but it's to avoid extra complexity for EffectOverride
797
+ gc_safe2, found = compute_gc_safe (setting)
798
+ if found
799
+ gc_safe = gc_safe2
800
+ continue
801
+ end
787
802
override = compute_assumed_setting (override, setting)
788
803
override === nothing &&
789
804
throw (ArgumentError (" `@assume_effects $setting ` not supported" ))
790
805
end
791
- return override
806
+ return override, gc_safe
792
807
end
793
808
794
809
struct EffectsOverride
835
850
836
851
const NUM_EFFECTS_OVERRIDES = 11 # sync with julia.h
837
852
853
+ function compute_gc_safe (setting)
854
+ if setting === :gc_safe
855
+ return (gc_safe= true , found= true )
856
+ elseif isexpr (setting, :call ) && setting. args[1 ] === :(! )
857
+ gc_safe2, found2 = compute_gc_safe (setting. args[2 ])
858
+ return (gc_safe= (! gc_safe2), found= found2)
859
+ elseif isa (setting, QuoteNode)
860
+ return compute_gc_safe (setting. value)
861
+ end
862
+ return (gc_safe= false , found= false )
863
+ end
864
+
838
865
function compute_assumed_setting (override:: EffectsOverride , @nospecialize (setting), val:: Bool = true )
839
866
if isexpr (setting, :call ) && setting. args[1 ] === :(! )
840
867
return compute_assumed_setting (override, setting. args[2 ], ! val)
0 commit comments