From 37d1458d583910994fb037f7e5ec35a5ed788c43 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 20 Jun 2024 05:54:01 +0000 Subject: [PATCH] Track `GlobalRef` consistently Companion PR to https://github.com/JuliaDebug/LoweredCodeUtils.jl/pull/107. With both of these and https://github.com/JuliaDebug/JuliaInterpreter.jl/pull/634, basic Revise functionality is working for me again on Julia master. --- src/lowered.jl | 33 +++++++++++++++++++++------------ src/parsing.jl | 2 +- src/utils.jl | 5 +++-- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/lowered.jl b/src/lowered.jl index 799c3989..5817dae0 100644 --- a/src/lowered.jl +++ b/src/lowered.jl @@ -85,10 +85,10 @@ Since the contents of such expression are difficult to analyze, it is generally safest to execute all such evals. """ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module, src::Core.CodeInfo, mode::Symbol) - edges = CodeEdges(src) + edges = CodeEdges(mod, src) # LoweredCodeUtils.print_with_code(stdout, src, edges) isrequired = fill(false, length(src.code)) - namedconstassigned = Dict{Symbol,Bool}() + namedconstassigned = Dict{GlobalRef,Bool}() evalassign = false for (i, stmt) in enumerate(src.code) if !isrequired[i] @@ -99,18 +99,24 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module, end end if isexpr(stmt, :const) - name = stmt.args[1]::Symbol - namedconstassigned[name] = false + name = stmt.args[1] + if isa(name, Symbol) + name = GlobalRef(mod, name) + end + namedconstassigned[name::GlobalRef] = false elseif isexpr(stmt, :(=)) lhs = (stmt::Expr).args[1] if isa(lhs, Symbol) + lhs = GlobalRef(mod, name) + end + if isa(lhs, GlobalRef) if haskey(namedconstassigned, lhs) namedconstassigned[lhs] = true end end if mode === :evalassign evalassign = isrequired[i] = true - if isa(lhs, Symbol) + if isa(lhs, GlobalRef) isrequired[edges.byname[lhs].succs] .= true # mark any `const` statements or other "uses" in this block end end @@ -119,7 +125,7 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module, if mode === :sigs for (name, isassigned) in namedconstassigned isassigned || continue - if isdefined(mod, name) + if isdefined(name.mod, name.name) empty!(edges.byname[name].succs) # avoid redefining `consts` in `:sigs` mode (fixes #789) end end @@ -225,7 +231,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod Core.eval(mod, ex) catch err (always_rethrow || isa(err, InterruptException)) && rethrow(err) - loc = location_string(whereis(frame)...) + loc = location_string(whereis(frame)) bt = trim_toplevel!(catch_backtrace()) throw(ReviseEvalException(loc, err, Any[(sf, 1) for sf in stacktrace(bt)])) end @@ -248,7 +254,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod methods_by_execution!(recurse, methodinfo, docexprs, frame, isrequired; mode=mode, kwargs...) catch err (always_rethrow || isa(err, InterruptException)) && (disablebp && foreach(enable, active_bp_refs); rethrow(err)) - loc = location_string(whereis(frame)...) + loc = location_string(whereis(frame)) sfs = [] # crafted for interaction with Base.show_backtrace frame = JuliaInterpreter.leaf(frame) while frame !== nothing @@ -309,10 +315,13 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra # However, it might have been followed by a thunk that defined a # method (issue #435), so we still need to check for additions. if !isempty(signatures) - file, line = whereis(frame.framecode, pc) - lnn = LineNumberNode(Int(line), Symbol(file)) - for sig in signatures - add_signature!(methodinfo, sig, lnn) + loc = whereis(frame.framecode, pc) + if loc !== nothing + file, line = loc + lnn = LineNumberNode(Int(line), Symbol(file)) + for sig in signatures + add_signature!(methodinfo, sig, lnn) + end end end pc = next_or_nothing!(frame) diff --git a/src/parsing.jl b/src/parsing.jl index 313bdf1b..8a8175ea 100644 --- a/src/parsing.jl +++ b/src/parsing.jl @@ -58,7 +58,7 @@ function process_source!(mod_exprs_sigs::ModuleExprsSigs, ex, filename, mod::Mod catch err bt = trim_toplevel!(catch_backtrace()) lnn = firstline(ex) - loc = location_string(lnn.file, lnn.line) + loc = location_string((lnn.file, lnn.line)) throw(ReviseEvalException(loc, err, Any[(sf, 1) for sf in stacktrace(bt)])) end end diff --git a/src/utils.jl b/src/utils.jl index 6767ba10..cdfc3be1 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -59,8 +59,9 @@ firstline(rex::RelocatableExpr) = firstline(rex.ex) newloc(methloc::LineNumberNode, ln, lno) = fixpath(ln) -location_string(file::AbstractString, line) = abspath(file)*':'*string(line) -location_string(file::Symbol, line) = location_string(string(file), line) +location_string((file, line)::Tuple{AbstractString, Any},) = abspath(file)*':'*string(line) +location_string((file, line)::Tuple{Symbol, Any},) = location_string(string(file), line) +location_string(::Nothing) = "unknown location" function linediff(la::LineNumberNode, lb::LineNumberNode) (isa(la.file, Symbol) && isa(lb.file, Symbol) && (la.file::Symbol === lb.file::Symbol)) || return typemax(Int)