New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Use Cassette.jl instead of Vinyl #11
Conversation
global pass seems to be working
Some additional fixes, feel free to merge in this PR: sp/cassette...maleadt:pr/11 |
Ok, so apart from the
|
|
src/analysis.jl
Outdated
end | ||
end | ||
|
||
exprtype(code, x) = typeof(x) | ||
exprtype(code, x::Expr) = x.typ | ||
exprtype(code, x::Expr) = Union{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should be called any more, so perhaps we can just remove it. The same information should be in the SSAValue type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, I meant to remove that. There's a bit of cruft around anyways.
src/analysis.jl
Outdated
|
||
rebuild(code, x) = x | ||
rebuild(code, x::QuoteNode) = x.value | ||
rebuild(code, x::Expr) = Expr(x.head, rebuild.(code, x.args)...) | ||
rebuild(code, x::SlotNumber) = code.slotnames[x.id] | ||
rebuild(code, x::Expr) = Expr(x.head, rebuild.(Ref(code), x.args)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this still need to be splatted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, seems that way. I thought there was a Expr(head, args)
constructor too.
(isexpr(ex, :(=)) && isexpr(ex.args[2], GlobalRef)) || return | ||
ref = ex.args[2] | ||
isconst(ref.mod, ref.name) || | ||
ex isa Expr || return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GlobalRefs can be top level as well, so this might be best expressed with prewalk
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in, this will catch statements of the form %5 = foo(Base.pi)
but not of the form %4 = Base.pi; %5 = foo(%4)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, seems to work fine (-ish, no clue why it says x + Main.y
instead of x + foo
):
julia> function f(x)
foo = y
x+foo
end
f (generic function with 1 method)
julia> @code_typed f(2)
CodeInfo(
2 1 ─ %1 = Main.y::Any │
3 │ %2 = (x + %1)::Any │
└── return %2 │
) => Any
julia> @trace f(2)
┌ Warning: uses global variable Main.y
│ method = f(x) in Main at none:2
└ @ Traceur none:2
┌ Warning: foo is assigned as Any
│ method = f(x) in Main at none:2
└ @ Traceur none:2
┌ Warning: dynamic dispatch to x + Main.y
│ method = f(x) in Main at none:2
└ @ Traceur none:3
┌ Warning: returns Any
│ method = f(x) in Main at none:2
└ @ Traceur none:-1
4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that's because this pass actually runs on the unoptimised code_typed, not the SSA IR of @code_typed
.
Okay, so except for the
because it operates on the optimized |
I expect that printing the function name and line is enough there.
…On Mon, 3 Sep 2018 at 13:56, Sebastian Pfitzner ***@***.***> wrote:
Okay, so except for the prewalk thing which I'm not entirely sure how to
handle I should have taken care of most of your points.
dispatch printing is pretty bad though:
julia> @trace naive_sum([1.0])
┌ Warning: s is assigned as Int64
│ method = naive_sum(xs) in Main at untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:390
└ @ Traceur untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:390
┌ Warning: s is assigned as Float64
│ method = naive_sum(xs) in Main at untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:390
└ @ Traceur untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:392
┌ Warning: dynamic dispatch to (isa)(φ (%15 => 0, %51 => %32), Float64)
│ method = naive_sum(xs) in Main at untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:390
└ @ Traceur untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:392
┌ Warning: dynamic dispatch to (isa)(φ (%15 => 0, %51 => %32), Int64)
│ method = naive_sum(xs) in Main at untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:390
└ @ Traceur untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:392
┌ Warning: returns Union{Float64, Int64}
│ method = naive_sum(xs) in Main at untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:390
└ @ Traceur untitled-3e45b0bd2d71ea51bb6331b5aaf260a2:-1
1.0
because it operates on the optimized code_typed. Not sure how to get back
to something sane from there.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#11 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACIY9uOCNk8qQyEtHR8QuxiwNw_WwBkNks5uXScBgaJpZM4V5Il1>
.
|
Hm, yeah, but we don't even have the right function there:
The dynamic dispatch is actually happening in |
Well, there isn't any dynamic dispatch happening in that function, thanks to the new union splitting. I should have mentioned that To actually get a dynamic dispatch for testing we probably need to use a global or |
Ok, the code works fine then:
|
|
Yeah, I was confused because we had that exact check in there already (via AFAICT everything works fine now. |
src/analysis.jl
Outdated
end | ||
for (i, l) in enumerate(code.code) | ||
ind = code.codelocs[i] | ||
ind = clamp(ind, 1, length(code.linetable)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should just set the line to nothing
in this case, otherwise it could be misleading
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or -1
, which would be in line with how Base handles that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that would be fine, as long as we do a reasonable printing.
src/analysis.jl
Outdated
idx += 1 | ||
(isexpr(ex, :(=)) && isexpr(ex.args[1], Core.SlotNumber)) || return | ||
typ = code.ssavaluetypes[idx] | ||
if typ isa Core.Compiler.Const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Core.Compiler.widenconst
would acheive the same thing here.
src/analysis.jl
Outdated
end | ||
end | ||
|
||
# return type | ||
|
||
function issmallunion(t) | ||
ts = Base.uniontypes(t) | ||
length(ts) == 1 && isconcretetype(ts) && return true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isconcretetype(ts::Vector)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isconcretetype(first(ts))
... :)
src/trace.jl
Outdated
@@ -1,3 +1,44 @@ | |||
# struct Trace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we planning to recover this? Seems best to leave a comment explaining why code is there, or delete.
src/trace.jl
Outdated
result = overdub(ctx, f, args...) | ||
analyse((a...) -> ctx.warn(Warning(a...)), C) | ||
return result | ||
function Cassette.prehook(ctx::TraceurCtx, f, args...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously this was (effectively) a posthook
; best to keep it that way unless there's a specific reason to change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reasoning for that? I mean it's (probably) trivial to change, but why is posthook
more appropriate here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reasoning is that it tends to give warnings in the "right order", in the sense that type inference issues tend to propagate up the stack rather than down. e.g. in f(x) = ...; g(x)
, f
using a global variable won't affect the inferability of g
, but g
doing so will likely break f
as well; so printing in post order gives you the root cause first followed by knock-on effects.
(The order to analysis passes is also designed to fit that rule, though it's obviously heuristic).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, makes sense.
Ok, I think I have resolved all of the above points. |
Ok this looks good. Awesome work @pfitzseb. |
No description provided.