-
-
Notifications
You must be signed in to change notification settings - Fork 232
Description
@c42f's PR JuliaLang/julia#35844 gives an invoke_in_world
that we could use to replace how we've currently been using GeneralizedGenerated in a way that is safer for general Julia code. Currently our build_function
has two routes: one that uses eval and generates an EvalFunc
, and the other which builds the function via GeneralizedGenerated. The eval version had to be created because the type from GeneralizedGenerated can break. If you have a million equations, you get a gigantic type and that just seems to do some outrageous unholy things to the compiler.
EvalFunc requires one to invoke in the latest, so the machinery is defined in DiffEqBase so that we have
https://github.com/SciML/DiffEqBase.jl/blob/master/src/solve.jl#L5-L8
and then https://github.com/SciML/DiffEqBase.jl/blob/master/src/solve.jl#L30 which basically gives us a hook to get around world age issues when GeneralizedGenerated is not used. This works but has all of the downsides of invokelatest.
However, this new invoke is definitely a good way forward. For example, when we generate the functions from the symbolic code, i.e. https://github.com/SciML/ModelingToolkit.jl/blob/master/src/systems/diffeqs/abstractodesystem.jl#L122-L152, instead of building just an EvalFunc
, we can make a WorldFunc
that capturers the WorldAge as type information. Then we can have a call on this object perform invoke_in_world at the right world age. Hopefully, storing the world age as type information will make this all inferred and just as fast as a standard Julia function? (that's a question for @c42f).
With this in place, we can remove GeneralizedGenerated usage because then the standard function would be safe due to invoking in the proper world. The only issue that would come up is then that this is not precompile safe because the generated code is made for a specific world. However, any function that is made to precompile is a function evaluated in a module scope, which means it's safe to just use eval and not invoke in the world, and so we just need a flag to turn off the WorldFunc wrapping. That should make the whole symbolic system generate functions that are both efficient and don't have world age issues, and not have the scaling issues of GG.