Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Compiler/src/ssair/EscapeAnalysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,32 @@ export
has_thrown_escape,
has_all_escape

const _TOP_MOD = ccall(:jl_base_relative_to, Any, (Any,), EscapeAnalysis)::Module
using Base: Base

# imports
import ._TOP_MOD: ==, getindex, setindex!
import Base: ==, getindex, setindex!
# usings
using Core: MethodMatch, SimpleVector, ifelse, sizeof
using Core.IR
using ._TOP_MOD: # Base definitions
@__MODULE__, @assert, @eval, @goto, @inbounds, @inline, @label, @noinline, @show,
using Base: # Base definitions
@__MODULE__, @assert, @eval, @goto, @inbounds, @inline, @label, @noinline,
@nospecialize, @specialize, BitSet, Callable, Csize_t, IdDict, IdSet, UnitRange, Vector,
copy, delete!, empty!, enumerate, error, first, get, get!, haskey, in, isassigned,
isempty, ismutabletype, keys, last, length, max, min, missing, pop!, push!, pushfirst!,
unwrap_unionall, !, !=, !==, &, *, +, -, :, <, <<, =>, >, |, ∈, ∉, ∩, ∪, ≠, ≤, ≥, ⊆,
hasintersect
using ..Compiler: # Core.Compiler specific definitions
using ..Compiler: # Compiler specific definitions
AbstractLattice, Bottom, IRCode, IR_FLAG_NOTHROW, InferenceResult, SimpleInferenceLattice,
argextype, fieldcount_noerror, hasintersect, has_flag, intrinsic_nothrow,
is_meta_expr_head, is_identity_free_argtype, isexpr, println, setfield!_nothrow,
singleton_type, try_compute_field, try_compute_fieldidx, widenconst, ⊑, Compiler

function include(x)
if !isdefined(_TOP_MOD.Base, :end_base_include)
function include(x::String)
if !isdefined(Base, :end_base_include)
# During bootstrap, all includes are relative to `base/`
x = ccall(:jl_prepend_string, Ref{String}, (Any, Any), "ssair/", x)
end
_TOP_MOD.include(@__MODULE__, x)
Compiler.include(@__MODULE__, x)
end

include("disjoint_set.jl")
Expand Down
12 changes: 4 additions & 8 deletions Compiler/src/ssair/disjoint_set.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,9 @@
# under the MIT license: https://github.com/JuliaCollections/DataStructures.jl/blob/master/License.md

# imports
import ._TOP_MOD:
length,
eltype,
union!,
push!
import Base: length, eltype, union!, push!
# usings
import ._TOP_MOD:
OneTo, collect, zero, zeros, one, typemax
import Base: OneTo, collect, zero, zeros, one, typemax

# Disjoint-Set

Expand All @@ -27,7 +22,8 @@ import ._TOP_MOD:
#
############################################################

_intdisjointset_bounds_err_msg(T) = "the maximum number of elements in IntDisjointSet{$T} is $(typemax(T))"
_intdisjointset_bounds_err_msg(@nospecialize T) =
"the maximum number of elements in IntDisjointSet{$T} is $(typemax(T))"

"""
IntDisjointSet{T<:Integer}(n::Integer)
Expand Down
23 changes: 9 additions & 14 deletions doc/src/devdocs/EscapeAnalysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,8 @@ This escape analysis aims to:
You can give a try to the escape analysis by loading the `EAUtils.jl` utility script that
defines the convenience entries `code_escapes` and `@code_escapes` for testing and debugging purposes:
```@repl EAUtils
using Base.Compiler: EscapeAnalysis # or `using Compiler: EscapeAnalysis` to use the stdlib version
let JULIA_DIR = normpath(Sys.BINDIR, "..", "share", "julia")
# load `EscapeAnalysis` module to define the core analysis code
include(normpath(JULIA_DIR, "Compiler", "src", "ssair", "EscapeAnalysis.jl"))
using .EscapeAnalysis
# load `EAUtils` module to define the utilities
include(normpath(JULIA_DIR, "Compiler", "test", "EAUtils.jl"))
using .EAUtils
end
Expand All @@ -37,19 +34,17 @@ Base.setindex!(x::SafeRef, v) = x.x = v;
Base.isassigned(x::SafeRef) = true;
get′(x) = isassigned(x) ? x[] : throw(x);

result = code_escapes((String,String,String,String)) do s1, s2, s3, s4
r1 = Ref(s1)
result = code_escapes((Base.RefValue{String},String,String,)) do r1, s2, s3
r2 = Ref(s2)
r3 = SafeRef(s3)
try
s1 = get′(r1)
ret = sizeof(s1)
catch err
global GV = err # will definitely escape `r1`
global GV = err # `r1` may escape
end
s2 = get′(r2) # still `r2` doesn't escape fully
s3 = get′(r3) # still `r3` doesn't escape fully
s4 = sizeof(s4) # the argument `s4` doesn't escape here
s2 = get′(r2) # `r2` doesn't escape
s3 = get′(r3) # `r3` doesn't escape
return s2, s3, s4
end
```
Expand Down Expand Up @@ -105,10 +100,10 @@ One distinctive design of this escape analysis is that it is fully _backward_,
i.e. escape information flows _from usages to definitions_.
For example, in the code snippet below, EA first analyzes the statement `return %1` and
imposes `ReturnEscape` on `%1` (corresponding to `obj`), and then it analyzes
`%1 = %new(Base.RefValue{String, _2}))` and propagates the `ReturnEscape` imposed on `%1`
to the call argument `_2` (corresponding to `s`):
`%1 = %new(Base.RefValue{Base.RefValue{String}, _2}))` and propagates the `ReturnEscape`
imposed on `%1` to the call argument `_2` (corresponding to `s`):
```@repl EAUtils
code_escapes((String,)) do s
code_escapes((Base.RefValue{String},)) do s
obj = Ref(s)
return obj
end
Expand All @@ -120,7 +115,7 @@ As a result this scheme enables a simple implementation of escape analysis,
e.g. `PhiNode` for example can be handled simply by propagating escape information
imposed on a `PhiNode` to its predecessor values:
```@repl EAUtils
code_escapes((Bool, String, String)) do cnd, s, t
code_escapes((Bool, Base.RefValue{String}, Base.RefValue{String})) do cnd, s, t
if cnd
obj = Ref(s)
else
Expand Down