Skip to content

Commit

Permalink
Merge pull request #17518 from JuliaLang/jn/grabbug5
Browse files Browse the repository at this point in the history
bug grabbag
  • Loading branch information
vtjnash authored Jul 21, 2016
2 parents 1fcb81c + 9b2810f commit 5fe9e53
Show file tree
Hide file tree
Showing 20 changed files with 148 additions and 121 deletions.
26 changes: 13 additions & 13 deletions base/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,32 @@ abstract AbstractREPL
answer_color(::AbstractREPL) = ""

type REPLBackend
"channel for AST"
repl_channel::Channel
"channel for results: (value, nothing) or (error, backtrace)"
response_channel::Channel
"flag indicating the state of this backend"
in_eval::Bool
ans
"current backend task"
backend_task::Task
REPLBackend(repl_channel, response_channel, in_eval, ans) =
new(repl_channel, response_channel, in_eval, ans)

REPLBackend(repl_channel, response_channel, in_eval) =
new(repl_channel, response_channel, in_eval)
end

function eval_user_input(ast::ANY, backend::REPLBackend)
iserr, lasterr, bt = false, (), nothing
iserr, lasterr = false, ((), nothing)
while true
try
if iserr
put!(backend.response_channel, (lasterr, bt))
put!(backend.response_channel, lasterr)
iserr, lasterr = false, ()
else
ans = backend.ans
# note: value wrapped in a non-syntax value to avoid evaluating
# possibly-invalid syntax (issue #6763).
eval(Main, :(ans = $(getindex)($(Any[ans]), 1)))
backend.in_eval = true
value = eval(Main, ast)
backend.in_eval = false
backend.ans = value
# note: value wrapped in a closure to ensure it doesn't get passed through expand
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
put!(backend.response_channel, (value, nothing))
end
break
Expand All @@ -70,14 +71,13 @@ function eval_user_input(ast::ANY, backend::REPLBackend)
println("SYSTEM ERROR: Failed to report error to REPL frontend")
println(err)
end
iserr, lasterr = true, err
bt = catch_backtrace()
iserr, lasterr = true, (err, catch_backtrace())
end
end
end

function start_repl_backend(repl_channel::Channel, response_channel::Channel)
backend = REPLBackend(repl_channel, response_channel, false, nothing)
backend = REPLBackend(repl_channel, response_channel, false)
backend.backend_task = @schedule begin
# include looks at this to determine the relative include path
# nothing means cwd
Expand Down
4 changes: 2 additions & 2 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ function eval_user_input(ast::ANY, show_value)
errcount, lasterr = 0, ()
else
ast = expand(ast)
value = eval(Main,ast)
eval(Main, :(ans = $(Expr(:quote, value))))
value = eval(Main, ast)
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
if !is(value,nothing) && show_value
if have_color
print(answer_color())
Expand Down
11 changes: 6 additions & 5 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ function argtype_decl(env, n, sig, i, nargs, isva) # -> (argname, argtype)
end
end
return s, string_with_env(env, "Vararg{", tt, ",", tn, "}")
elseif t == String
return s, "String"
end
return s, string_with_env(env, t)
end
Expand All @@ -43,15 +41,15 @@ function arg_decl_parts(m::Method)
end
li = m.lambda_template
file, line = "", 0
if li !== nothing
if li !== nothing && isdefined(li, :slotnames)
argnames = li.slotnames[1:li.nargs]
decls = Any[argtype_decl(:tvar_env => tv, argnames[i], m.sig, i, li.nargs, li.isva)
for i = 1:li.nargs]
if isdefined(li, :def)
file, line = li.def.file, li.def.line
end
else
decls = Any["" for i = 1:length(m.sig.parameters)]
decls = Any[("", "") for i = 1:length(m.sig.parameters)]
end
return tv, decls, file, line
end
Expand All @@ -76,7 +74,10 @@ function show(io::IO, m::Method; kwtype::Nullable{DataType}=Nullable{DataType}()
tv, decls, file, line = arg_decl_parts(m)
ft = m.sig.parameters[1]
d1 = decls[1]
if ft <: Function &&
if m.sig === Tuple
print(io, m.name)
decls = Any[(), ("...", "")]
elseif ft <: Function &&
isdefined(ft.name.module, ft.name.mt.name) &&
ft == typeof(getfield(ft.name.module, ft.name.mt.name))
print(io, ft.name.mt.name)
Expand Down
9 changes: 9 additions & 0 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ uncompressed_ast(l::LambdaInfo) =
# Printing code representations in IR and assembly
function _dump_function(f, t::ANY, native, wrapper, strip_ir_metadata, dump_module)
ccall(:jl_is_in_pure_context, Bool, ()) && error("native reflection cannot be used from generated functions")
if isa(f, Core.Builtin)
throw(ArgumentError("argument is not a generic function"))
end
t = tt_cons(Core.Typeof(f), to_tuple_type(t))
llvmf = ccall(:jl_get_llvmf, Ptr{Void}, (Any, Bool, Bool), t, wrapper, native)

Expand Down Expand Up @@ -363,6 +366,9 @@ end

function code_typed(f::ANY, types::ANY=Tuple; optimize=true)
ccall(:jl_is_in_pure_context, Bool, ()) && error("code reflection cannot be used from generated functions")
if isa(f, Core.Builtin)
throw(ArgumentError("argument is not a generic function"))
end
types = to_tuple_type(types)
asts = []
for x in _methods(f,types,-1)
Expand All @@ -380,6 +386,9 @@ end

function return_types(f::ANY, types::ANY=Tuple)
ccall(:jl_is_in_pure_context, Bool, ()) && error("code reflection cannot be used from generated functions")
if isa(f, Core.Builtin)
throw(ArgumentError("argument is not a generic function"))
end
types = to_tuple_type(types)
rt = []
for x in _methods(f,types,-1)
Expand Down
23 changes: 18 additions & 5 deletions base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,23 @@ function show(io::IO, ::MIME"text/plain", f::Function)
end
end

function show(io::IO, ::MIME"text/plain", l::LambdaInfo)
show(io, l)
# Fix slot names and types in function body
ast = uncompressed_ast(l)
if ast !== nothing
println(io)
lambda_io = IOContext(io, :LAMBDAINFO => l)
if isdefined(l, :slotnames)
lambda_io = IOContext(lambda_io, :LAMBDA_SLOTNAMES => lambdainfo_slotnames(l))
end
body = Expr(:body)
body.args = ast
body.typ = l.rettype
show(lambda_io, body)
end
end

function show(io::IO, ::MIME"text/plain", r::LinSpace)
# show for linspace, e.g.
# linspace(1,3,7)
Expand Down Expand Up @@ -389,11 +406,7 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs::Vector=Any[])
arg_types_param = Any[arg_types.parameters...]
# Displays the closest candidates of the given function by looping over the
# functions methods and counting the number of matching arguments.
if isa(ex.f, Tuple)
f = ex.f[1]
else
f = ex.f
end
f = ex.f
ft = typeof(f)
lines = []
# These functions are special cased to only show if first argument is matched.
Expand Down
47 changes: 16 additions & 31 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ function show(io::IO, p::Pair)
isa(p.second,Pair) && print(io, "(")
show(io, p.second)
isa(p.second,Pair) && print(io, ")")
nothing
end

function show(io::IO, m::Module)
Expand Down Expand Up @@ -259,30 +260,21 @@ function lambdainfo_slotnames(l::LambdaInfo)
end
printnames[i] = printname
end
printnames
return printnames
end

function show(io::IO, l::LambdaInfo)
if isdefined(l, :def)
if (l === l.def.lambda_template)
if l === l.def.lambda_template
print(io, "LambdaInfo template for ")
show(io, l.def)
println(io)
else
print(io, "LambdaInfo for ")
show_lambda_types(io, l.specTypes.parameters)
println(io)
show_lambda_types(io, l)
end
else
println(io, "Toplevel LambdaInfo thunk")
end
# Fix slot names and types in function body
lambda_io = IOContext(IOContext(io, :LAMBDAINFO => l),
:LAMBDA_SLOTNAMES => lambdainfo_slotnames(l))
body = Expr(:body)
body.args = uncompressed_ast(l)
body.typ = l.rettype
show(lambda_io, body)
print(io, "Toplevel LambdaInfo thunk")
end
end

function show_delim_array(io::IO, itr::Union{AbstractArray,SimpleVector}, op, delim, cl,
Expand Down Expand Up @@ -565,15 +557,6 @@ show_unquoted(io::IO, ex::LabelNode, ::Int, ::Int) = print(io, ex.label, ":
show_unquoted(io::IO, ex::GotoNode, ::Int, ::Int) = print(io, "goto ", ex.label)
show_unquoted(io::IO, ex::GlobalRef, ::Int, ::Int) = print(io, ex.mod, '.', ex.name)

function show_unquoted(io::IO, ex::LambdaInfo, ::Int, ::Int)
if isdefined(ex, :specTypes)
print(io, "LambdaInfo for ")
show_lambda_types(io, ex.specTypes.parameters)
else
show(io, ex)
end
end

function show_unquoted(io::IO, ex::Slot, ::Int, ::Int)
typ = isa(ex,TypedSlot) ? ex.typ : Any
slotid = ex.id
Expand Down Expand Up @@ -744,7 +727,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
# binary operator (i.e. "x + y")
elseif func_prec > 0 # is a binary operator
na = length(func_args)
if na == 2 || (na > 2 && func in (:+, :++, :*))
if (na == 2 || (na > 2 && func in (:+, :++, :*))) && all(!isa(a, Expr) || a.head !== :... for a in func_args)
sep = " $func "
if func_prec <= prec
show_enclosed_list(io, '(', func_args, sep, ')', indent, func_prec, true)
Expand Down Expand Up @@ -983,20 +966,22 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
show(io, ex.head)
for arg in args
print(io, ", ")
if isa(arg, LambdaInfo) && isdefined(arg, :specTypes)
show_lambda_types(io, arg.specTypes.parameters)
else
show(io, arg)
end
show(io, arg)
end
print(io, "))")
end
show_type && show_expr_type(io, ex.typ, emphstate)
nothing
end

function show_lambda_types(io::IO, sig::SimpleVector)
# print a method signature tuple
function show_lambda_types(io::IO, li::LambdaInfo)
# print a method signature tuple for a lambda definition
if li.specTypes === Tuple
print(io, li.def.name, "(...)")
return
end

sig = li.specTypes.parameters
ft = sig[1]
if ft <: Function && isempty(ft.parameters) &&
isdefined(ft.name.module, ft.name.mt.name) &&
Expand Down
21 changes: 9 additions & 12 deletions base/stacktraces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Stack information representing execution context, with the following fields:
The name of the function containing the execution context.
- `outer_linfo::Nullable{LambdaInfo}`
- `linfo::Nullable{LambdaInfo}`
The LambdaInfo containing the execution context (if it could be found).
Expand All @@ -29,18 +29,14 @@ Stack information representing execution context, with the following fields:
The line number in the file containing the execution context.
- `inlined_file::Symbol`
The path to the file containing the context for inlined code.
- `inlined_line::Int`
The line number in the file containing the context for inlined code.
- `from_c::Bool`
True if the code is from C.
- `inlined::Bool`
True if the code is from an inlined frame.
- `pointer::Int64`
Representation of the pointer to the execution context as returned by `backtrace`.
Expand All @@ -57,6 +53,7 @@ immutable StackFrame # this type should be kept platform-agnostic so that profil
linfo::Nullable{LambdaInfo}
"true if the code is from C"
from_c::Bool
"true if the code is from an inlined frame"
inlined::Bool
"representation of the pointer to the execution context as returned by `backtrace`"
pointer::Int64 # Large enough to be read losslessly on 32- and 64-bit machines.
Expand Down Expand Up @@ -195,10 +192,10 @@ function show_spec_linfo(io::IO, frame::StackFrame)
end
else
linfo = get(frame.linfo)
if isdefined(linfo, :specTypes)
Base.show_lambda_types(io, linfo.specTypes.parameters)
if isdefined(linfo, :def)
Base.show_lambda_types(io, linfo)
else
print(io, linfo.name)
Base.show(io, linfo)
end
end
end
Expand Down
13 changes: 8 additions & 5 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,10 @@ JL_DLLEXPORT jl_lambda_info_t *jl_new_lambda_info_uninit(void)
(jl_lambda_info_t*)jl_gc_alloc(ptls, sizeof(jl_lambda_info_t),
jl_lambda_info_type);
li->code = NULL;
li->slotnames = li->slotflags = NULL;
li->slottypes = li->ssavaluetypes = NULL;
li->slotnames = NULL;
li->slotflags = NULL;
li->slottypes = NULL;
li->ssavaluetypes = NULL;
li->rettype = (jl_value_t*)jl_any_type;
li->sparam_syms = jl_emptysvec;
li->sparam_vals = jl_emptysvec;
Expand Down Expand Up @@ -586,7 +588,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void)
m->specializations.unknown = jl_nothing;
m->sig = NULL;
m->tvars = NULL;
m->ambig = NULL;
m->ambig = jl_nothing;
m->roots = NULL;
m->module = ptls->current_module;
m->lambda_template = NULL;
Expand All @@ -612,7 +614,6 @@ jl_method_t *jl_new_method(jl_lambda_info_t *definition, jl_sym_t *name, jl_tupl
if (jl_svec_len(tvars) == 1)
tvars = (jl_svec_t*)jl_svecref(tvars, 0);
m->tvars = tvars;
m->ambig = jl_nothing;
JL_GC_PUSH1(&m);
// the front end may add this lambda to multiple methods; make a copy if so
jl_method_t *oldm = definition->def;
Expand Down Expand Up @@ -1114,7 +1115,9 @@ JL_DLLEXPORT jl_datatype_t *jl_new_bitstype(jl_value_t *name, jl_datatype_t *sup
jl_datatype_t *bt = jl_new_datatype((jl_sym_t*)name, super, parameters,
jl_emptysvec, jl_emptysvec, 0, 0, 0);
uint32_t nbytes = (nbits + 7) / 8;
uint32_t alignm = nbytes > MAX_ALIGN ? MAX_ALIGN : nbytes;
uint32_t alignm = next_power_of_two(nbytes);
if (alignm > MAX_ALIGN)
alignm = MAX_ALIGN;
bt->size = nbytes;
bt->layout = jl_get_layout(0, alignm, 0, NULL);
return bt;
Expand Down
7 changes: 7 additions & 0 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1071,9 +1071,16 @@ void *jl_get_llvmf(jl_tupletype_t *tt, bool getwrapper, bool getdeclarations)
}
}
if (linfo == NULL) {
// no function found for argument tuple type
JL_GC_POP();
return NULL;
}
if (linfo->def->lambda_template->code == jl_nothing) {
// not a generic function
JL_GC_POP();
return NULL;
}

// make sure to compile this normally first,
// since `emit_function` doesn't handle recursive compilation correctly
linfo = jl_compile_for_dispatch(linfo);
Expand Down
Loading

4 comments on commit 5fe9e53

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

@Sacha0
Copy link
Member

@Sacha0 Sacha0 commented on 5fe9e53 Jul 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrevels Are the aberrations in this report related to ee5e231#commitcomment-18326454 ? Best!

@jrevels
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, that only affected that day's report. This report is correctly comparing against the 7/21 build; there seem to be actual regressions here.

Please sign in to comment.