From c2fb5b03e260e97cd66e76549acf210054453368 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 31 Dec 2020 12:34:20 -0600 Subject: [PATCH] Improve precompilability with noninferrable filename After #259, the result of `filename(q)` is not inferrable. This uses "the kernel trick" to provide a single point where the result must be inferred, and an `invokelatest` to prevent the abstract signature from being inferred. It then precompiles the `::String` variant. Consequently, with respect to latency this should get us back to where we were before #259. --- src/loadsave.jl | 10 +++++++--- src/precompile.jl | 6 ++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/loadsave.jl b/src/loadsave.jl index a5dd85dc..63730ed8 100644 --- a/src/loadsave.jl +++ b/src/loadsave.jl @@ -182,14 +182,18 @@ end # Handlers for formatted files/streams for fn in (:load, :loadstreaming, :metadata) + fn_func_name = Symbol(fn, "_filename") gen2_func_name = Symbol("fileio_", fn) @eval function $fn(@nospecialize(q::Formatted), @nospecialize(args...); @nospecialize(options...)) + Base.invokelatest($fn_func_name, q, filename(q), args...; options...) + end + @eval function $fn_func_name(@nospecialize(q::Formatted), filename, @nospecialize(args...); @nospecialize(options...)) if unknown(q) - isfile(filename(q)) || open(filename(q)) # force systemerror + isfile(filename) || open(filename) # force systemerror throw(UnknownFormat(q)) end if q isa File - !isfile(filename(q)) && throw(ArgumentError("No file exists at given path: $(filename(q))")) + !isfile(filename) && throw(ArgumentError("No file exists at given path: $(filename)")) end libraries = applicable_loaders(q) failures = Any[] @@ -207,7 +211,7 @@ for fn in (:load, :loadstreaming, :metadata) push!(failures, (e, q)) end end - handle_exceptions(failures, "loading $(repr(filename(q)))") + handle_exceptions(failures, "loading $(repr(filename))") end end diff --git a/src/precompile.jl b/src/precompile.jl index 3a74a69b..39392b62 100644 --- a/src/precompile.jl +++ b/src/precompile.jl @@ -9,6 +9,12 @@ function _precompile_() @assert precompile(Tuple{typeof(load),File}) @assert precompile(Tuple{typeof(load),Formatted}) @assert precompile(Tuple{typeof(load),String}) + @assert precompile(Tuple{typeof(FileIO.load_filename),Formatted,String}) + if isdefined(Base, :bodyfunction) + fbody = Base.bodyfunction(which(FileIO.load_filename, (Formatted, String))) + @assert precompile(fbody, (Any, typeof(FileIO.load_filename), Formatted, String)) + @assert precompile(fbody, (Any, typeof(FileIO.load_filename), Formatted, String, Vararg{Any,100})) + end @assert precompile(Tuple{typeof(query),String}) @assert precompile(Tuple{typeof(query),IOStream})