diff --git a/base/loading.jl b/base/loading.jl index 125e9b1302fb5..5cb6ad5467f81 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2444,7 +2444,21 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in # create a temporary file in `cachepath` directory, write the cache in it, # write the checksum, _and then_ atomically move the file to `cachefile`. mkpath(cachepath) - cache_objects = JLOptions().use_pkgimages != 0 + if JLOptions().use_pkgimages == 0 + cache_objects = false + else + if JLOptions().tracked_path == C_NULL + cache_objects = true + else + tracked_path = unsafe_string(JLOptions().tracked_path) + # disable pkgimages if srcpath falls within a code-coverage or allocation-tracking path + # TODO: disable if any includes fall within tracked_path, not just the srcpath + # harder because includes aren't currently known before cache generation + # or implement https://github.com/JuliaLang/julia/issues/51412 + cache_objects = !startswith(path, tracked_path) + end + end + tmppath, tmpio = mktemp(cachepath) if cache_objects @@ -3159,6 +3173,7 @@ end return stale_cachefile(PkgId(""), UInt128(0), modpath, cachefile; ignore_loaded) end @constprop :none function stale_cachefile(modkey::PkgId, build_id::UInt128, modpath::String, cachefile::String; ignore_loaded::Bool = false) + tracked_path = JLOptions().tracked_path == C_NULL ? "" : unsafe_string(JLOptions().tracked_path) io = open(cachefile, "r") try checksum = isvalid_cache_header(io) @@ -3170,10 +3185,19 @@ end if isempty(modules) return true # ignore empty file end - if ccall(:jl_match_cache_flags, UInt8, (UInt8,), flags) == 0 + current_flags = ccall(:jl_cache_flags, UInt8, ()) + if !isempty(tracked_path) + for chi in includes + startswith(chi.filename, tracked_path) || continue + @debug "Allowing pkgimages=no for $modkey because it falls in coverage/allocation tracking path $tracked_path" + current_flags &= 0b11111110 # disable pkgimages flag + break + end + end + if ccall(:jl_match_cache_flags, UInt8, (UInt8, UInt8), flags, current_flags) == 0 @debug """ Rejecting cache file $cachefile for $modkey since the flags are mismatched - current session: $(CacheFlags()) + current session: $(CacheFlags(current_flags)) cache file: $(CacheFlags(flags)) """ return true @@ -3284,11 +3308,14 @@ end if !ispath(f) _f = fixup_stdlib_path(f) if isfile(_f) && startswith(_f, Sys.STDLIB) + check_if_tracked(_f, tracked_path, cachefile) && return true continue end @debug "Rejecting stale cache file $cachefile because file $f does not exist" return true end + check_if_tracked(f, tracked_path, cachefile) && return true + if ftime_req >= 0.0 # this is an include_dependency for which we only recorded the mtime ftime = mtime(f) @@ -3341,6 +3368,18 @@ end end end +function check_if_tracked(included_file::String, tracked_path::String, cachefile::String) + if JLOptions().use_pkgimages != 0 && JLOptions().code_coverage == 3 && occursin(tracked_path, included_file) + @debug "Rejecting cache file $cachefile because included file $included_file is being tracked by --code-coverage=@$tracked_path" + return true + end + if JLOptions().use_pkgimages != 0 && JLOptions().malloc_log == 3 && occursin(tracked_path, included_file) + @debug "Rejecting cache file $cachefile because included file $included_file is being tracked by --track-allocation=@$tracked_path" + return true + end + return false +end + """ @__FILE__ -> String diff --git a/base/util.jl b/base/util.jl index fe04eaf04bd47..89472cdc8b525 100644 --- a/base/util.jl +++ b/base/util.jl @@ -245,7 +245,7 @@ function julia_cmd(julia=joinpath(Sys.BINDIR, julia_exename()); cpu_target::Unio push!(addflags, "--pkgimages=no") else # If pkgimage is set, malloc_log and code_coverage should not - @assert opts.malloc_log == 0 && opts.code_coverage == 0 + @assert opts.malloc_log in (0, 3) && opts.code_coverage in (0, 3) end return `$julia -C$cpu_target -J$image_file $addflags` end diff --git a/src/init.c b/src/init.c index fef3e73bd2d06..976971ad7347f 100644 --- a/src/init.c +++ b/src/init.c @@ -804,7 +804,8 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) #endif if ((jl_options.outputo || jl_options.outputbc || jl_options.outputasm) && - (jl_options.code_coverage || jl_options.malloc_log)) { + (jl_options.code_coverage == 1 || jl_options.code_coverage == 2 || + jl_options.malloc_log == 1 || jl_options.malloc_log == 2)) { jl_error("cannot generate code-coverage or track allocation information while generating a .o, .bc, or .s output file"); } diff --git a/src/jloptions.c b/src/jloptions.c index f9443ed8f5704..1341b4c7a09f2 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -860,10 +860,17 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) "This is a bug, please report it.", c); } } - if (codecov || malloclog) { + if (codecov == 1 || codecov == 2) { if (pkgimage_explicit && jl_options.use_pkgimages) { jl_errorf("julia: Can't use --pkgimages=yes together " - "with --track-allocation or --code-coverage."); + "with --code-coverage=user|all"); + } + jl_options.use_pkgimages = 0; + } + if (malloclog == 1 || malloclog == 2) { + if (pkgimage_explicit && jl_options.use_pkgimages) { + jl_errorf("julia: Can't use --pkgimages=yes together " + "with --track-allocation=user|all"); } jl_options.use_pkgimages = 0; } diff --git a/src/staticdata.c b/src/staticdata.c index 72fac1c3c845e..d86dddc96d8fd 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -3494,7 +3494,7 @@ static jl_value_t *jl_validate_cache_file(ios_t *f, jl_array_t *depmods, uint64_ "Precompile file header verification checks failed."); } uint8_t flags = read_uint8(f); - if (pkgimage && !jl_match_cache_flags(flags)) { + if (pkgimage && !jl_match_cache_flags(flags, jl_cache_flags())) { return jl_get_exceptionf(jl_errorexception_type, "Pkgimage flags mismatch"); } if (!pkgimage) { diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index 384c479b10f58..12203ff5d784c 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -599,7 +599,8 @@ JL_DLLEXPORT uint8_t jl_cache_flags(void) { // OOICCDDP uint8_t flags = 0; - flags |= (jl_options.use_pkgimages & 1); // 0-bit + // don't use use_pkgimages here because no outputo overrides it + flags |= ((jl_options.outputo == NULL || jl_options.outputo[0] == '\0') | 1); // 0-bit flags |= (jl_options.debug_level & 3) << 1; // 1-2 bit flags |= (jl_options.check_bounds & 3) << 3; // 3-4 bit flags |= (jl_options.can_inline & 1) << 5; // 5-bit @@ -607,12 +608,11 @@ JL_DLLEXPORT uint8_t jl_cache_flags(void) return flags; } -JL_DLLEXPORT uint8_t jl_match_cache_flags(uint8_t flags) +JL_DLLEXPORT uint8_t jl_match_cache_flags(uint8_t cache_flags, uint8_t current_flags) { // 1. Check which flags are relevant - uint8_t current_flags = jl_cache_flags(); uint8_t supports_pkgimage = (current_flags & 1); - uint8_t is_pkgimage = (flags & 1); + uint8_t is_pkgimage = (cache_flags & 1); // For .ji packages ignore other flags if (!supports_pkgimage && !is_pkgimage) { @@ -621,12 +621,12 @@ JL_DLLEXPORT uint8_t jl_match_cache_flags(uint8_t flags) // 2. Check all flags, execept opt level must be exact uint8_t mask = (1 << OPT_LEVEL)-1; - if ((flags & mask) != (current_flags & mask)) + if ((cache_flags & mask) != (current_flags & mask)) return 0; // 3. allow for higher optimization flags in cache - flags >>= OPT_LEVEL; + cache_flags >>= OPT_LEVEL; current_flags >>= OPT_LEVEL; - return flags >= current_flags; + return cache_flags >= current_flags; } // "magic" string and version header of .ji file