diff --git a/bin/generate_builtins.jl b/bin/generate_builtins.jl index 70a0c573..e442c7b0 100644 --- a/bin/generate_builtins.jl +++ b/bin/generate_builtins.jl @@ -11,6 +11,7 @@ const RECENTLY_ADDED = Core.Builtin[ Core.finalizer, Core._compute_sparams, Core._svec_ref, Core.compilerbarrier, Core.memoryref, Core.memoryref_isassigned, Core.memoryrefget, Core.memoryrefoffset, Core.memoryrefset!, + #=Core.current_scope=# ] # Builtins present in 1.6, not builtins (potentially still normal functions) anymore const RECENTLY_REMOVED = GlobalRef.(Ref(Core), [ @@ -187,13 +188,13 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool) print(io, """ $head f === $fstr - if !expand - argswrapped = getargs(args, frame) - return Some{Any}($fstr(argswrapped...)) - end - # This uses the original arguments to avoid looking them up twice - # See #442 - return Expr(:call, invoke, args[2:end]...) + if !expand + argswrapped = getargs(args, frame) + return Some{Any}($fstr(argswrapped...)) + end + # This uses the original arguments to avoid looking them up twice + # See #442 + return Expr(:call, invoke, args[2:end]...) """) continue elseif f === Core._call_latest @@ -211,6 +212,22 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool) end return maybe_recurse_expanded_builtin(frame, new_expr) """) + continue + elseif f === Core.current_scope + print(io, +""" + elseif @static isdefined(Core, :current_scope) && f === Core.current_scope + if nargs == 0 + if isempty(frame.framedata.current_scopes) + return Some{Any}(nothing) + else + return Some{Any}(frame.framedata.current_scopes[end]) + end + else + return Some{Any}(Core.current_scope(getargs(args, frame)...)) + end +""") + continue end id = findfirst(isequal(f), Core.Compiler.T_FFUNC_KEY) diff --git a/src/builtins.jl b/src/builtins.jl index 5bc58ba2..198a5470 100644 --- a/src/builtins.jl +++ b/src/builtins.jl @@ -94,8 +94,6 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool) push!(new_expr.args, QuoteNode(x)) end return maybe_recurse_expanded_builtin(frame, new_expr) - elseif f === Core._call_latest - return Some{Any}(Core._call_latest(getargs(args, frame)...)) elseif @static isdefined(Core, :_compute_sparams) && f === Core._compute_sparams return Some{Any}(Core._compute_sparams(getargs(args, frame)...)) elseif f === Core._equiv_typedef @@ -126,6 +124,16 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool) else return Some{Any}(Core.compilerbarrier(getargs(args, frame)...)) end + elseif @static isdefined(Core, :current_scope) && f === Core.current_scope + if nargs == 0 + if isempty(frame.framedata.current_scopes) + return Some{Any}(nothing) + else + return Some{Any}(frame.framedata.current_scopes[end]) + end + else + return Some{Any}(Core.current_scope(getargs(args, frame)...)) + end elseif @static isdefined(Core, :donotdelete) && f === Core.donotdelete return Some{Any}(Core.donotdelete(getargs(args, frame)...)) elseif @static isdefined(Core, :finalizer) && f === Core.finalizer @@ -227,13 +235,13 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool) return Some{Any}(getglobal(getargs(args, frame)...)) end elseif f === invoke - if !expand - argswrapped = getargs(args, frame) - return Some{Any}(invoke(argswrapped...)) - end - # This uses the original arguments to avoid looking them up twice - # See #442 - return Expr(:call, invoke, args[2:end]...) + if !expand + argswrapped = getargs(args, frame) + return Some{Any}(invoke(argswrapped...)) + end + # This uses the original arguments to avoid looking them up twice + # See #442 + return Expr(:call, invoke, args[2:end]...) elseif f === isa if nargs == 2 return Some{Any}(isa(@lookup(frame, args[2]), @lookup(frame, args[3]))) diff --git a/src/construct.jl b/src/construct.jl index 8bb93470..614bb5a9 100644 --- a/src/construct.jl +++ b/src/construct.jl @@ -272,7 +272,7 @@ function prepare_framedata(framecode, argvals::Vector{Any}, lenv::SimpleVector=e if length(junk_framedata) > 0 olddata = pop!(junk_framedata) locals, ssavalues, sparams = olddata.locals, olddata.ssavalues, olddata.sparams - exception_frames, last_reference = olddata.exception_frames, olddata.last_reference + exception_frames, current_scopes, last_reference = olddata.exception_frames, olddata.current_scopes, olddata.last_reference last_exception = olddata.last_exception callargs = olddata.callargs resize!(locals, ns) @@ -282,6 +282,7 @@ function prepare_framedata(framecode, argvals::Vector{Any}, lenv::SimpleVector=e # for check_isdefined to work properly, we need sparams to start out unassigned resize!(sparams, 0) empty!(exception_frames) + empty!(current_scopes) resize!(last_reference, ns) last_exception[] = _INACTIVE_EXCEPTION.instance else @@ -289,6 +290,7 @@ function prepare_framedata(framecode, argvals::Vector{Any}, lenv::SimpleVector=e ssavalues = Vector{Any}(undef, ng) sparams = Vector{Any}(undef, 0) exception_frames = Int[] + current_scopes = Any[] last_reference = Vector{Int}(undef, ns) callargs = Any[] last_exception = Ref{Any}(_INACTIVE_EXCEPTION.instance) @@ -317,7 +319,8 @@ function prepare_framedata(framecode, argvals::Vector{Any}, lenv::SimpleVector=e isa(T, TypeVar) && continue # only fill concrete types sparams[i] = T end - FrameData(locals, ssavalues, sparams, exception_frames, last_exception, caller_will_catch_err, last_reference, callargs) + return FrameData(locals, ssavalues, sparams, exception_frames, current_scopes, + last_exception, caller_will_catch_err, last_reference, callargs) end """ @@ -334,6 +337,7 @@ end function prepare_frame_caller(caller::Frame, framecode::FrameCode, args::Vector{Any}, lenv::SimpleVector) caller_will_catch_err = !isempty(caller.framedata.exception_frames) || caller.framedata.caller_will_catch_err caller.callee = frame = prepare_frame(framecode, args, lenv, caller_will_catch_err) + copy!(frame.framedata.current_scopes, caller.framedata.current_scopes) frame.caller = caller return frame end diff --git a/src/interpret.jl b/src/interpret.jl index ff8248dc..57ffdc2b 100644 --- a/src/interpret.jl +++ b/src/interpret.jl @@ -397,9 +397,6 @@ function eval_rhs(@nospecialize(recurse), frame, node::Expr) elseif head === :copyast val = (node.args[1]::QuoteNode).value return isa(val, Expr) ? copy(val) : val - elseif head === :enter - # XXX This seems to be dead code - return length(frame.framedata.exception_frames) elseif head === :boundscheck return true elseif head === :meta || head === :inbounds || head === :loopinfo || @@ -486,8 +483,12 @@ function step_expr!(@nospecialize(recurse), frame, @nospecialize(node), istoplev for i = 1:length(node.args) targ = node.args[i] targ === nothing && continue - frame.framecode.src.code[(targ::SSAValue).id] === nothing && continue + enterstmt = frame.framecode.src.code[(targ::SSAValue).id] + enterstmt === nothing && continue pop!(data.exception_frames) + if isdefined(enterstmt, :scope) + pop!(data.current_scopes) + end end end elseif node.head === :pop_exception @@ -568,6 +569,9 @@ function step_expr!(@nospecialize(recurse), frame, @nospecialize(node), istoplev elseif @static (isdefined(Core.IR, :EnterNode) && true) && isa(node, Core.IR.EnterNode) rhs = node.catch_dest push!(data.exception_frames, rhs) + if isdefined(node, :scope) + push!(data.current_scopes, @lookup(frame, node.scope)) + end else rhs = @lookup(frame, node) end diff --git a/src/optimize.jl b/src/optimize.jl index 5d879470..a6b180cb 100644 --- a/src/optimize.jl +++ b/src/optimize.jl @@ -70,7 +70,17 @@ function renumber_ssa!(stmts::Vector{Any}, ssalookup) stmts[i] = ReturnNode(SSAValue(ssalookup[val.id])) end elseif @static (isdefined(Core.IR, :EnterNode) && true) && isa(stmt, Core.IR.EnterNode) - stmts[i] = Core.IR.EnterNode(jumplookup(ssalookup, stmt.catch_dest)) + new_catch_dest = jumplookup(ssalookup, stmt.catch_dest) + if isdefined(stmt, :scope) + scope = stmt.scope + if isa(scope, Core.SSAValue) + stmts[i] = Core.IR.EnterNode(new_catch_dest, SSAValue(jumplookup(ssalookup, scope.id))) + else + stmts[i] = Core.IR.EnterNode(new_catch_dest, ) + end + else + stmts[i] = Core.IR.EnterNode(new_catch_dest) + end end end return stmts diff --git a/src/packagedef.jl b/src/packagedef.jl index c14fbe2a..db0f7863 100644 --- a/src/packagedef.jl +++ b/src/packagedef.jl @@ -43,6 +43,12 @@ if !isdefined(Base, Symbol("@something")) end end +if isdefined(Base, :ScopedValues) + using Base: ScopedValues.Scope +else + const Scope = Any +end + include("types.jl") include("utils.jl") include("construct.jl") diff --git a/src/types.jl b/src/types.jl index a4424c34..08b8dbc1 100644 --- a/src/types.jl +++ b/src/types.jl @@ -204,6 +204,7 @@ struct FrameData ssavalues::Vector{Any} sparams::Vector{Any} exception_frames::Vector{Int} + current_scopes::Vector{Scope} last_exception::Base.RefValue{Any} caller_will_catch_err::Bool last_reference::Vector{Int} diff --git a/test/interpret.jl b/test/interpret.jl index d93f09cb..feaec441 100644 --- a/test/interpret.jl +++ b/test/interpret.jl @@ -997,3 +997,12 @@ end # test for using generic functions that were previously builtin func_arrayref(a, i) = Core.arrayref(true, a, i) @test 2 == @interpret func_arrayref([1,2,3], 2) + +@static if !isdefined(Base, :ScopedValues) +const sval = ScopedValue(1) +sval_func() = @with sval => 2 begin + return sval[] +end +@test 2 == @interpret sval_func() +@test 1 == @interpret getindex(sval) +end