Skip to content

Commit

Permalink
resolve all globals to GlobalRef very early
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Jul 10, 2015
1 parent 14af2d1 commit 7908246
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 120 deletions.
93 changes: 0 additions & 93 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1921,77 +1921,6 @@ function _sym_repl(s::Union{Symbol,GenSym}, from1, from2, to1, to2, deflt)
return deflt
end

# return an expr to evaluate "from.sym" in module "to"
function resolve_relative(sym, locals, args, from, to, orig)
if sym in locals || sym in args
return GlobalRef(from, sym)
end
if is(from,to)
return orig
end
const_from = (isconst(from,sym) && isdefined(from,sym))
const_to = (isconst(to,sym) && isdefined(to,sym))
if const_from
if const_to && is(eval(from,sym), eval(to,sym))
return orig
end
m = _topmod()
if is(from, m) || is(from, Core)
return TopNode(sym)
end
end
return GlobalRef(from, sym)
end

# annotate symbols with their original module for inlining
function resolve_globals(e::ANY, locals, args, from, to, env1, env2)
if isa(e,Symbol)
s = e::Symbol
if contains_is(env1, s) || contains_is(env2, s)
return s
end
return resolve_relative(s, locals, args, from, to, s)
end
if isa(e,SymbolNode)
s = e::SymbolNode
name = s.name
if contains_is(env1, name) || contains_is(env2, name)
return s
end
return resolve_relative(name, locals, args, from, to, s)
end
if !isa(e,Expr)
return e
end
e = e::Expr
if e.head === :(=)
# remove_redundant_temp_vars can only handle Symbols
# on the LHS of assignments, so we make sure not to put
# something else there
e2 = resolve_globals(e.args[1]::Union{Symbol,GenSym}, locals, args, from, to, env1, env2)
if isa(e2, GlobalRef)
# abort when trying to inline a function which assigns to a global
# variable in a different module, since `Mod.X=V` isn't allowed
throw(e2)
# e2 = e2::GetfieldNode
# e = Expr(:call, top_setfield, e2.value, qn(e2.name),
# resolve_globals(e.args[2], locals, args, from, to, env1, env2))
# e.typ = e2.typ
else
e.args[1] = e2::Union{Symbol,GenSym}
e.args[2] = resolve_globals(e.args[2], locals, args, from, to, env1, env2)
end
elseif !is(e.head,:line)
for i=1:length(e.args)
subex = e.args[i]
if !(isa(subex,Number) || isa(subex,AbstractString))
e.args[i] = resolve_globals(subex, locals, args, from, to, env1, env2)
end
end
end
e
end

# count occurrences up to n+1
function occurs_more(e::ANY, pred, n)
if isa(e,Expr)
Expand Down Expand Up @@ -2320,7 +2249,6 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as

body = Expr(:block)
body.args = without_linenums(ast.args[3].args)::Array{Any,1}
need_mod_annotate = true
cost::Int = 1000
if incompletematch
cost *= 4
Expand Down Expand Up @@ -2351,7 +2279,6 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as
end
body.args = Any[Expr(:return, newcall)]
ast = Expr(:lambda, newnames, Any[[], locals, [], 0], body)
need_mod_annotate = false
needcopy = false
else
return NF
Expand Down Expand Up @@ -2434,26 +2361,6 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as
end
end

# annotate variables in the body expression with their module
if need_mod_annotate
mfrom = linfo.module; mto = (inference_stack::CallStack).mod
enc_capt = enclosing_ast.args[2][2]
if !isempty(enc_capt)
# add captured var names to list of locals
enc_vars = vcat(enc_locllist, map(vi->vi[1], enc_capt))
else
enc_vars = enc_locllist
end
try
body = resolve_globals(body, enc_vars, enclosing_ast.args[1], mfrom, mto, args, spnames)
catch ex
if isa(ex,GlobalRef)
return NF
end
rethrow(ex)
end
end

# see if each argument occurs only once in the body expression
stmts = []
stmts_free = true # true = all entries of stmts are effect_free
Expand Down
13 changes: 9 additions & 4 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ show(io::IO, s::Symbol) = show_unquoted_quote_expr(io, s, 0, 0)
# While this isn’t true of ALL show methods, it is of all ASTs.

typealias ExprNode Union{Expr, QuoteNode, SymbolNode, LineNumberNode,
LabelNode, GotoNode, TopNode}
LabelNode, GotoNode, TopNode, GlobalRef}
# Operators have precedence levels from 1-N, and show_unquoted defaults to a
# precedence level of 0 (the fourth argument). The top-level print and show
# methods use a precedence of -1 to specially allow space-separated macro syntax
Expand Down Expand Up @@ -410,6 +410,7 @@ show_unquoted(io::IO, ex::LineNumberNode, ::Int, ::Int) = show_linenumber(io, ex
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::TopNode, ::Int, ::Int) = print(io,"top(",ex.name,')')
show_unquoted(io::IO, ex::GlobalRef, ::Int, ::Int) = print(io, ex.mod, '.', ex.name)

function show_unquoted(io::IO, ex::SymbolNode, ::Int, ::Int)
print(io, ex.name)
Expand Down Expand Up @@ -494,16 +495,20 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
# function call
elseif head == :call && nargs >= 1
func = args[1]
func_prec = operator_precedence(func)
fname = isa(func,GlobalRef) ? func.name : func
func_prec = operator_precedence(fname)
if func_prec > 0 || fname in uni_ops
func = fname
end
func_args = args[2:end]

if in(ex.args[1], (:box, TopNode(:box), :throw)) || ismodulecall(ex)
show_expr_type_emphasize::Bool = show_type = false
end

# scalar multiplication (i.e. "100x")
if (func == :(*) && length(func_args)==2 &&
isa(func_args[1], Real) && isa(func_args[2], Symbol))
if (func == :(*) &&
length(func_args)==2 && isa(func_args[1], Real) && isa(func_args[2], Symbol))
if func_prec <= prec
show_enclosed_list(io, '(', func_args, "", ')', indent, func_prec)
else
Expand Down
63 changes: 62 additions & 1 deletion src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ static jl_value_t *full_list_of_lists(value_t e, int expronly)
return (jl_value_t*)ar;
}

static jl_value_t *resolve_globals(jl_value_t *expr, jl_lambda_info_t *lam);

static jl_value_t *scm_to_julia(value_t e, int expronly)
{
int en = jl_gc_enable(0);
Expand Down Expand Up @@ -317,7 +319,9 @@ static jl_value_t *scm_to_julia_(value_t e, int eo)
jl_cellset(ex->args, i, scm_to_julia_(car_(e), eo));
e = cdr_(e);
}
return (jl_value_t*)jl_new_lambda_info((jl_value_t*)ex, jl_emptysvec);
jl_lambda_info_t *nli = jl_new_lambda_info((jl_value_t*)ex, jl_emptysvec);
resolve_globals(nli->ast, nli);
return (jl_value_t*)nli;
}

e = cdr_(e);
Expand Down Expand Up @@ -971,6 +975,63 @@ jl_value_t *skip_meta(jl_array_t *body)
return body1;
}

static int in_vinfo_array(jl_array_t *a, jl_value_t *v)
{
size_t i, l=jl_array_len(a);
for(i=0; i<l; i++) {
if (jl_cellref(jl_cellref(a,i),0) == v)
return 1;
}
return 0;
}

static int in_sym_array(jl_array_t *a, jl_value_t *v)
{
size_t i, l=jl_array_len(a);
for(i=0; i<l; i++) {
if (jl_cellref(a,i) == v)
return 1;
}
return 0;
}

static jl_value_t *resolve_globals(jl_value_t *expr, jl_lambda_info_t *lam)
{
if (jl_is_symbol(expr)) {
if (lam->module == NULL)
return expr;
int is_local = in_vinfo_array(jl_lam_vinfo((jl_expr_t*)lam->ast), expr) ||
in_vinfo_array(jl_lam_capt((jl_expr_t*)lam->ast), expr) ||
in_sym_array(jl_lam_staticparams((jl_expr_t*)lam->ast), expr);
if (!is_local)
return jl_module_globalref(lam->module, (jl_sym_t*)expr);
}
else if (jl_is_lambda_info(expr)) {
jl_lambda_info_t *l = (jl_lambda_info_t*)expr;
(void)resolve_globals(l->ast, l);
}
else if (jl_is_expr(expr)) {
jl_expr_t *e = (jl_expr_t*)expr;
if (e->head == lambda_sym) {
(void)resolve_globals(jl_exprarg(e,2), lam);
}
else if (jl_is_toplevel_only_expr(expr) || e->head == const_sym || e->head == copyast_sym ||
e->head == global_sym || e->head == quote_sym || e->head == inert_sym ||
e->head == line_sym || e->head == meta_sym) {
}
else {
size_t i = 0;
if (e->head == method_sym || e->head == abstracttype_sym || e->head == compositetype_sym ||
e->head == bitstype_sym || e->head == macro_sym || e->head == module_sym)
i++;
for(; i < jl_array_len(e->args); i++) {
jl_exprargset(e, i, resolve_globals(jl_exprarg(e,i), lam));
}
}
}
return expr;
}

#ifdef __cplusplus
}
#endif
Loading

0 comments on commit 7908246

Please sign in to comment.