Replies: 15 comments
-
What's the point? Is it to save stack space for the unused variables? To avoid unnecessarily loading the fields/properties? Aren't both of those optimizations that the JIT could do? |
Beta Was this translation helpful? Give feedback.
-
This does not just avoid the unnecessary locals, bound variables are also directly assigned.
Does "loading" properties actually make sense here? unused property getters just won't be called. |
Beta Was this translation helpful? Give feedback.
-
You mean that it skips calling
Right, I was assuming that getters are trivial (read: can be inlined and optimized away if unused). My point is: I think those are all optimizations that the JIT could do with no modification to the language. If you think this is a performance problem, maybe asking for the JIT to optimize this kind of code better would make more sense thank asking for the language to change? (The one exception are non-trivial getters, which the JIT probably won't be able to completely optimize away anytime soon. I'm not sure that's enough to justify this feature.) |
Beta Was this translation helpful? Give feedback.
-
While I agree that this is just to "optimize" the generated code aside form some syntax candy, I can no longer buy the assumptions about things JIT hopefully probably should do. Is there any way to actually test if it does the inlining? |
Beta Was this translation helpful? Give feedback.
-
Might as well get rid of the block requirement too: void Deconstruct(out this.Foo, out this.Bar); (Maybe just in the case of all parameters being |
Beta Was this translation helpful? Give feedback.
-
With the "out this" Deconstruct method, would the method call be omitted in favor or property access always, or is this only for when some of the desconstruction is being discarded? |
Beta Was this translation helpful? Give feedback.
-
It's always omitted (assuming that's ok wrt side effects), because with "out this" parameters, we always know that which position corresponds to which member. Perhaps we should require "all or none" of parameters to be |
Beta Was this translation helpful? Give feedback.
-
There are two options here:
I don't see how would option 2 be worth it, even if you could make it happen sooner than option 1.
The simple option is to use SharpLab, which now also supports decompiling. Though I believe it uses .Net Framework x86 JIT, so the output is not representative of the state of the art. (It also currently doesn't seem to support tuples and deconstruction, but that's probably temporary.) The right option is to follow this guide to build CoreCLR from source and use it to output the assembly. Using that approach and this code, the results are: ; var (x, _) = e;
mov eax, dword ptr [rcx]
mov rax, gword ptr [rcx+8]
; var x = e.Foo;
mov rax, gword ptr [rcx+8] So, the To sum up: After looking at the generated assembly, I'm even more convinced this does not make sense. In the case of trivial property getters (which I think are the common case for |
Beta Was this translation helpful? Give feedback.
-
Ok, just one question. How would JIT compiler know that I'm not interested in sideeffects of get_Bar? I agree that deconstruction is defined as calling Deconstruct, but with discards I've made it clear that I'm not interested in that particular value and I'd prefer to avoid those sideeffects. |
Beta Was this translation helpful? Give feedback.
-
It wouldn't. But I think that having side-effects in |
Beta Was this translation helpful? Give feedback.
-
I'm not talking about Deconstruct method itself. There's a higher chance for Bar getter to have sideeffects. Like caching the result the first time it's being read. |
Beta Was this translation helpful? Give feedback.
-
@alrz Yeah, I meant, |
Beta Was this translation helpful? Give feedback.
-
So it wouldn't be rare. I'm trying to say that the only reason you want to define a Deconstruct method is to give an "order" to members to be able to use deconstruction and later, positional patterns. If it comes at the cost of evaluating every member at the time of use (in presence of discards), I'd say that a discard is not what it meant to be. |
Beta Was this translation helpful? Give feedback.
-
If side effects of all properties need to be evaluated at the same time (as opposed to only the side effects of properties which are not discarded), then the standard Or really the properties should be written to force evaluation of each other. It is likely bad design to force the caller to be aware of such a constraint, especially if the properties are directly visible outside the class. |
Beta Was this translation helpful? Give feedback.
-
@svick "this" parameter defaults are already being considered as a way of making "With" methods work. This proposal is a small increment to that. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Currently, discards always pass a local to the
Deconsturct
method (except for well-knownValueTuple
in which case we use element fields directly),With
out this
parameters we can keep the target member in metadata and use it instead, removing discarded locals.This should also work for extension methods,
Note: Assignments should still be emitted inside the method in case we're using an older compiler.
This relates to #277 and will be more significant with recursive patterns in general. Once we have those concepts, the number of locals will increase under the hood.
Update: We can require all of the parameters to be "out this" and remove the body to avoid potential side effects, since we're skipping the call to Deconstruct altogether.
--
Open question: Should this be only permitted for
Deconstruct
methods?Open question: Should this be only permitted for
out
parameters?Open question: Should this be only permitted for
this
values?Note: this is not to be confused with "caller-receiver parameters".
Beta Was this translation helpful? Give feedback.
All reactions