Skip to content

Commit

Permalink
this fixes #265, mostly
Browse files Browse the repository at this point in the history
adds a world counter
and threads it everywhere
and tracks all backedges
add tests for some versions of #265
also updates the compile test to be world-aware
and add docs for method replacement / world age

note that MethodTables need to Base.serialized in a world-aware manner

and MethodError needs to be world aware

the age in MethodInstance is a copy of the value returned by typemap lookup
since we don't currently have a mechanism for accessing that value directly
plus, this seems easier anyways

handle MethodInstance age range updates correctly means
only updating them in-place when that doesn't potentially invalidate other
consumers that might also be holding a reference to it
and propagate this through the callers to type-inference

virtual edges are tracked via exact signature tuple types

inference is pure for backedges meaning that
we only add backedges that exist at the end of inference
and then add them to the correct MethodInstance object
which also make codegen caching world-aware

min/max validity of ml-matches results is threaded out of jl_matching_methods into inference
  eventually should probably switch this to use a Ref,
  or return the value, or something similarly more efficient than a
  singleton Array, but currently refpointer.jl is not part of Core.Inference

incremental deserialize is aware of world counter logic
by handling the follow cases:
 - "free-standing" methods (where age is at the default of 0), probably from a toplevel thunk or deserialize
 - garbage methods (really we just want to delete these, but, oh well). this is something inferred to have been replaced
 - applicable methods (this is the overwhelming majority of cases)
the logic between TypeMapEntry, Method, and MethodInstance all agree on these concepts

this uses Expr(:body) as an argument to eval to ensure that eval won't call expand,
which ensures that QuoteNode works correctly and the eval is reasonably fast
  • Loading branch information
vtjnash committed Dec 22, 2016
1 parent d47f24b commit 0b8f0b7
Show file tree
Hide file tree
Showing 48 changed files with 2,017 additions and 743 deletions.
6 changes: 3 additions & 3 deletions base/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function eval_user_input(ast::ANY, backend::REPLBackend)
value = eval(Main, ast)
backend.in_eval = false
# note: value wrapped in a closure to ensure it doesn't get passed through expand
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing)))
put!(backend.response_channel, (value, nothing))
end
break
Expand Down Expand Up @@ -153,9 +153,9 @@ function print_response(errio::IO, val::ANY, bt, show_value::Bool, have_color::B
if val !== nothing && show_value
try
if specialdisplay === nothing
display(val)
eval(Main, Expr(:body, Expr(:return, Expr(:call, display, QuoteNode(val)))))
else
display(specialdisplay,val)
eval(Main, Expr(:body, Expr(:return, Expr(:call, specialdisplay, QuoteNode(val)))))
end
catch err
println(errio, "Error showing value of type ", typeof(val), ":")
Expand Down
5 changes: 3 additions & 2 deletions base/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,12 @@ function get_type_call(expr::Expr)
found ? push!(args, typ) : push!(args, Any)
end
# use _methods_by_ftype as the function is supplied as a type
mt = Base._methods_by_ftype(Tuple{ft, args...}, -1)
world = typemax(UInt)
mt = Base._methods_by_ftype(Tuple{ft, args...}, -1, world)
length(mt) == 1 || return (Any, false)
m = first(mt)
# Typeinference
params = Core.Inference.InferenceParams()
params = Core.Inference.InferenceParams(world)
return_type = Core.Inference.typeinf_type(m[3], m[1], m[2], true, params)
return_type === nothing && return (Any, false)
return (return_type, true)
Expand Down
3 changes: 3 additions & 0 deletions base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ Alternatively, there is no unique most-specific method.
type MethodError <: Exception
f
args
world::UInt
MethodError(f::ANY, args::ANY, world::UInt) = new(f, args, world)
end
MethodError(f::ANY, args::ANY) = MethodError(f, args, typemax(UInt))

"""
EOFError()
Expand Down
10 changes: 10 additions & 0 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ unsafe_convert{T}(::Type{T}, x::T) = x

typealias NTuple{N,T} Tuple{Vararg{T,N}}


# primitive array constructors
(::Type{Array{T,N}}){T,N}(d::NTuple{N,Int}) =
ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d)
Expand Down Expand Up @@ -338,6 +339,15 @@ Array{T}(::Type{T}, m::Int,n::Int) = Array{T,2}(m,n)
Array{T}(::Type{T}, m::Int,n::Int,o::Int) = Array{T,3}(m,n,o)


# primitive Symbol constructors
Symbol(s::String) = Symbol(s.data)
function Symbol(a::Array{UInt8,1})
return ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int),
ccall(:jl_array_ptr, Ptr{UInt8}, (Any,), a),
Intrinsics.arraylen(a))
end


# docsystem basics
macro doc(x...)
atdoc(x...)
Expand Down
7 changes: 4 additions & 3 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,13 @@ function eval_user_input(ast::ANY, show_value)
else
ast = expand(ast)
value = eval(Main, ast)
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
if value!==nothing && show_value
eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing)))
if !(value === nothing) && show_value
if have_color
print(answer_color())
end
try display(value)
try
eval(Main, Expr(:body, Expr(:return, Expr(:call, display, QuoteNode(value)))))
catch err
println(STDERR, "Evaluation succeeded, but an error occurred while showing value of type ", typeof(value), ":")
rethrow(err)
Expand Down
5 changes: 0 additions & 5 deletions base/coreimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ if !isdefined(Main, :Base)
(::Type{T}){T}(arg) = convert(T, arg)::T
end

# Symbol constructors
Symbol(s::String) = Symbol(s.data)
Symbol(a::Array{UInt8,1}) =
ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int32), a, length(a))

# core array operations
include("array.jl")
include("abstractarray.jl")
Expand Down
2 changes: 1 addition & 1 deletion base/docs/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ..esc, ..push!, ..getindex, ..current_module, ..unsafe_load, ..Csize_t
function doc!(str, ex)
ptr = unsafe_load(Core.Intrinsics.cglobal(:jl_filename, Ptr{UInt8}))
len = ccall(:strlen, Csize_t, (Ptr{UInt8},), ptr)
file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Int32), ptr, len)
file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Csize_t), ptr, len)
line = unsafe_load(Core.Intrinsics.cglobal(:jl_lineno, Int32)) # Cint
push!(DOCS, (current_module(), ex, str, file, line))
end
Expand Down
6 changes: 4 additions & 2 deletions base/error.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ systemerror(p, b::Bool; extrainfo=nothing) = b ? throw(Main.Base.SystemError(str
assert(x) = x ? nothing : throw(Main.Base.AssertionError())
macro assert(ex, msgs...)
msg = isempty(msgs) ? ex : msgs[1]
if !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
if isa(msg, AbstractString)
msg = msg # pass-through
elseif !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
# message is an expression needing evaluating
msg = :(Main.Base.string($(esc(msg))))
elseif isdefined(Main, :Base) && isdefined(Main.Base, :string)
Expand All @@ -47,7 +49,7 @@ macro assert(ex, msgs...)
# string() might not be defined during bootstrap
msg = :(Main.Base.string($(Expr(:quote,msg))))
end
:($(esc(ex)) ? $(nothing) : throw(Main.Base.AssertionError($msg)))
return :($(esc(ex)) ? $(nothing) : throw(Main.Base.AssertionError($msg)))
end

# NOTE: Please keep the constant values specified below in sync with the doc string
Expand Down
Loading

0 comments on commit 0b8f0b7

Please sign in to comment.