-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #6341: Revise purity checking #6377
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
Conversation
There is some confusion on terms that needs to be fixed. Step 1: Make `SimplyPure apply to paths only. The only point where it is used is in eta expansion to answer the question whether in a partial application `f(e, _)` the expression `e` should be lifted out, giving `{ val x = e; y => f(x, y) }` instead of `y => f(e, y)`. With the change, closures and new expressions are never simply pure, so are always lifted out. This can reduce the number of allocations, if the lambda is applied several times.
test performance please |
performance test scheduled: 1 job(s) in queue, 1 running. |
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/6377/ to see the changes. Benchmarks is based on merging with master (22ba798) |
A pure expression such as `(a + b).c` of constant type is now characterized again as a pure path (since it will be eventually replaced by that constant, which is a path). This fixes instability problems in pickling and improves inlining. For instance `assert(0 == 0)` is reduced to `()` again with this change.
test performance please |
performance test scheduled: 1 job(s) in queue, 1 running. |
@@ -841,12 +858,15 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => | |||
|
|||
object TreeInfo { | |||
class PurityLevel(val x: Int) extends AnyVal { | |||
def >= (that: PurityLevel): Boolean = x >= that.x | |||
def min(that: PurityLevel): PurityLevel = new PurityLevel(x min that.x) | |||
def >= (that: PurityLevel): Boolean = (x & that.x) == that.x |
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.
This change in the semantics of x
deserves some documentation.
val Idempotent: PurityLevel = new PurityLevel(1) | ||
val Impure: PurityLevel = new PurityLevel(0) | ||
|
||
val PurePath: PurityLevel = new PurityLevel(7) | ||
val IdempotentPath: PurityLevel = new PurityLevel(5) |
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.
Maybe should be more explicit
val PurePath: PurityLevel = new PurityLevel(Path.x | Pure.x)
val IdempotentPath: PurityLevel = new PurityLevel(Path.x | Idempotent.x)
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/6377/ to see the changes. Benchmarks is based on merging with master (1521576) |
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.
Checked various cases around the things that could break that condition in Inliner and LGTM.
There is some confusion on terminology that needs to be fixed.
Step 1: Make SimplyPure apply to paths only.
The only point where it is used is in eta expansion to answer the question
whether in a partial application
f(e, _)
the expressione
should belifted out, giving
{ val x = e; y => f(x, y) }
instead ofy => f(e, y)
.With the change, closures and new expressions are never simply pure, so
are always lifted out. This can reduce the number of allocations, if the
lambda is applied several times.
Step 2: Split the property that something is a path from the property that something is pure, or idempotent.
Step 3: Require an idempotent path in the critical Inliner code.