-
Notifications
You must be signed in to change notification settings - Fork 3.1k
@nullOut annotation #10959
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
base: 2.13.x
Are you sure you want to change the base?
@nullOut annotation #10959
Conversation
😎🆒 |
I don't understand Seth's emojis so ❤️ and 🚀. |
I took another look at
scala> val ll: LazyList[Int] = 1 #:: 2 #:: 3 #:: ll
val ll: LazyList[Int] = LazyList(<not computed>)
scala> ll.mkString
val res0: String = 123<cycle> Even though that could be considered an inconsistency, it seems desired (scala/collection-strawman#550, scala/bug#8680). Cycle detection uses the 2x/1x iterator idea (Floyd's Algorithm). So for a very long non-cyclic LazyList, the slow pointer points to the middle of the list when the fast one reaches the end. So at least half of the list cannot be GC'd. I don't see how we could fix it. |
260cea2
to
8f785ec
Compare
@-ing @NthPortal and @scala/collections |
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.
neat! I don't know enough the compiler to be confident in saying anything about the implementation, but it look decent to me
Hello, optimizer!
|
8f785ec
to
d783f87
Compare
8fd5c74
to
4fa73fe
Compare
`this: @nullOut` or `local: @nullOut` sets the local variable slot to `null` after loading the value on the stack. Mixin forwarders, static mixin accessors and bridges set the receiver local to `null` if the target method is annotated `@nullOut`, for example. Co-authored-by: Stefan Zeiger <[email protected]>
Needs a restarr to work! The forwarder / alias `IterableOnceOps./:` uses `@nullOut` to clear the `this` reference before calling `foldLeft`. The annotation is also on the method itself to ensure mixin forwarders (generated in the subclass) and the static mixin accessor (generated in the trait) null out the receiver before invoking `/:`. After removing `LazyList.foldLeft`, it inherits the implementation from LinearSeqOps. That method again uses `@nullOut` twice, once to clear `this` when it's no longer needed, and once on the method for the generated accessors. I think we should *not* use `@nullOut` everywhere in the standard library, only on methods that cannot be overridden in LazyList, like `/:`. `@nullOut` works correctly on `mkString` too, but unfortunately the `addString` override in LazyList prevents GC of processed elements due to cycle detection.
4fa73fe
to
a4216e5
Compare
Includes changes from #10937.
Continuation of #7990.
this: @nullOut
orlocal: @nullOut
sets the local variable slot tonull
after loading the value on the stack.Mixin forwarders, static mixin accessors and bridges set the receiver
local to
null
if the target method is annotated@nullOut
.As a test, use
@nullOut
for the forwarder / aliasIterableOnceOps./:
.It uses
@nullOut
to clearthe
this
reference before callingfoldLeft
. The annotation isalso on the method itself to ensure mixin forwarders (generated in
the subclass) and the static mixin accessor (generated in the trait)
null out the receiver before invoking
/:
.After removing
LazyList.foldLeft
, it inherits the implementationfrom LinearSeqOps. That method again uses
@nullOut
twice, onceto clear
this
when it's no longer needed, and once on the methodfor the generated accessors.
I think we should not use
@nullOut
everywhere in the standardlibrary, only on methods that cannot be overridden in LazyList.
So, for final methods like
/:
ormkString
.