Skip to content

Commit

Permalink
interpret structs correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk committed Oct 8, 2020
1 parent 4eef8ca commit 4ffa225
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/TypeProfiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import LoweredCodeUtils:
istypedef, ismethod

import JuliaInterpreter:
evaluate_call_recurse!, bypass_builtins, maybe_evaluate_builtin, collect_args
evaluate_call_recurse!, bypass_builtins, maybe_evaluate_builtin, collect_args, is_return

using FileWatching, Requires

Expand Down
8 changes: 7 additions & 1 deletion src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,12 @@ function abstract_eval_value(interp::TPInterpreter, @nospecialize(e), vtypes::Va
end

function abstract_eval_statement(interp::TPInterpreter, @nospecialize(e), vtypes::VarTable, sv::InferenceState)
if istoplevel(sv)
if interp.not_abstracted[get_cur_pc(sv)]
return Any # bail out if it has been interpreted
end
end

ret = @invoke abstract_eval_statement(interp::AbstractInterpreter, e, vtypes::VarTable, sv::InferenceState)

# assign virtual global variable
Expand Down Expand Up @@ -371,7 +377,7 @@ function set_virtual_globalvar!(interp, mod, name, @nospecialize(t))
update = true
val.t, val.id, (val.edge_sym, val.li)
else
@warn "TypeProfiler.jl can't trace updates of global variable that already have values"
@warn "TypeProfiler.jl can't trace updates of global variable that already have values" mod name val
return
end
else
Expand Down
5 changes: 5 additions & 0 deletions src/abstractinterpreterinterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ struct TPInterpreter <: AbstractInterpreter
# disables caching of native remarks (that may vastly speed up profiling time)
filter_native_remarks::Bool

# toplevel profiling (skip inference on actually interpreted statements)
not_abstracted::BitVector

function TPInterpreter(world = get_world_counter();
inf_params = gen_inf_params(),
opt_params = gen_opt_params(),
Expand All @@ -33,6 +36,7 @@ struct TPInterpreter <: AbstractInterpreter
reports = [],
exception_reports = [],
filter_native_remarks = true,
not_abstracted = [],
)
@assert !opt_params.inlining "inlining should be disabled"

Expand All @@ -45,6 +49,7 @@ struct TPInterpreter <: AbstractInterpreter
reports,
exception_reports,
filter_native_remarks,
not_abstracted,
)
end
end
Expand Down
30 changes: 27 additions & 3 deletions src/virtualprocess.jl
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ function virtual_process!(toplevelex::Expr,
not_abstracted = partial_interpret!(interp′, virtualmod, src)

# TODO: construct partial `CodeInfo` from remaining abstract statements ?
all(not_abstracted) && continue # bail out if nothing to profile (just a performance optimization)
# bail out if nothing to profile (just a performance optimization)
all(is_return(last(src.code)) ? not_abstracted[begin:end-1] : not_abstracted) && continue

interp = TPInterpreter(; # world age gets updated to take in newly added methods defined by `ActualInterpreter`
inf_params = InferenceParams(interp),
Expand All @@ -224,6 +225,7 @@ function virtual_process!(toplevelex::Expr,
compress = may_compress(interp),
discard_trees = may_discard_trees(interp),
filter_native_remarks = interp.filter_native_remarks,
not_abstracted = not_abstracted,
)

profile_toplevel!(interp, virtualmod, src)
Expand Down Expand Up @@ -257,14 +259,36 @@ end
# select statements that should be not abstracted away, but rather actually interpreted
function select_statements(src)
stmts = src.code

not_abstracted = map(stmts) do stmt
istypedef(stmt) && return true
ismethod(stmt) && return true
# special case `include` calls
isinclude(stmt) && return true

# interpret method definitions
ismethod(stmt) && return true

# interpret type definitions
istypedef(stmt) && return true
# add more statements necessary for the first time interpretation of a type definition
# TODO: maybe upstream these into LoweredCodeUtils.jl ?
if isexpr(stmt, :(=))
stmt = stmt.args[2] # rhs
end
if isexpr(stmt, :call)
f = stmt.args[1]
if isa(f, GlobalRef)
f.mod === Core && f.name in (:_setsuper!, :_equiv_typedef, :_typebody!) && return true
end
if isa(f, QuoteNode)
f.value in (Core._setsuper!, Core._equiv_typedef, Core._typebody!) && return true
end
end

return false
end

lines_required!(not_abstracted, src, CodeEdges(src))

return not_abstracted
end

Expand Down
11 changes: 7 additions & 4 deletions test/test_virtualprocess.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,22 @@ end
let
vmod = gen_virtual_module()
res, interp = @profile_toplevel vmod begin
foo = rand(Bool)
gb = rand(Bool)

struct Foo
b::Bool
Foo(b = foo) = new(b)
Foo(b = gb) = new(b)
end

Foo()
foo = Foo(gb)
end

# global variables aren't evaluated but kept in `interp` instead
@test get_virtual_globalvar(vmod, :foo) isa VirtualGlobalVariable
gb = get_virtual_globalvar(vmod, :gb)
@test gb isa VirtualGlobalVariable && gb.t Bool
@test isdefined(vmod, :Foo)
foo = get_virtual_globalvar(vmod, :foo)
@test foo isa VirtualGlobalVariable && foo.t vmod.Foo
@test isempty(res.toplevel_error_reports)
@test isempty(res.inference_error_reports)
end
Expand Down

0 comments on commit 4ffa225

Please sign in to comment.