-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Use in_guaranteed for let captures #29812
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
@swift-ci benchmark |
@meg-gupta before this goes in can you fix up the git history? |
@gottesmm Will do |
Performance: -O
Code size: -O
Performance: -Osize
Code size: -Osize
Performance: -Onone
Code size: -swiftlibsHow to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
d297d9a
to
20ddbf1
Compare
@swift-ci benchmark |
Performance: -O
Code size: -O
Performance: -Osize
Code size: -Osize
Performance: -Onone
Code size: -swiftlibsHow to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
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'm really happy to see usages of Inout_Aliasable go away.
Ideally we would get rid of capture.isNoEscape()
too. Is that a possibility? We should be able to promote box captures to stack in the SIL optimizer, instead of relying on Sema/SILGen setting capture.isNoEscape()
.
Can we use |
@slavapestov that is a much larger change. In reality what we need to do is make it so that inout_aliasable is either in_guaranteed or inout. It would let us eliminate a bunch of unfortunate things in the code base. |
20ddbf1
to
baba446
Compare
@swift-ci test |
Build failed |
Build failed |
@slavapestov In certain cases there is a mismatch between the capture.isNoEscape in the frontend and outType.isNoEscape in IRGen. This can cause issue for generating code for the in_guaranteed param. I am working on changes to get rid of this. Will post an update soon. |
@swift-ci please test |
@swift-ci please benchmark |
Build failed |
Build failed |
@swift-ci please test |
@swift-ci please benchmark |
Build failed |
@swift-ci please test |
@swift-ci Please test OS X platform |
@swift-ci please benchmark |
@slavapestov exclusivity is a prerequisite. But now the no-escape closure representation needs to be fixed.
It's very clear to me how this should be fixed, and I wrote up a design proposal for it years ago but it has been lower priority than bug fixing. |
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.
@meg-gupta I'm very happy you got this working. It's a very clean design that defines away a category of memory bugs.
Please address these issues in a follow-up PR:
- Comments should be 80 columns
In TypeConverter::getDeclCaptureKind
:
-
assert that Immutable captures are address-only
-
Fix the above check for opaque values. Note that SILOpaqueValues has
not effect on SIL calling convention, so whether it is enabled should probably
have no effect on the CaptureKind.
In TempRValueOpts:
- collectLoads: this looks correct, but please comment why mark_dependence base operand is safe to consider a load, and why the value operand needs to be transitive (otherwise we would miscompile!)
In irgen::emitFunctionPartialApplication()
:
- In the block comment please explain what is happening clearly. You or @aschwaighofer or @rjmccall can explain this better than I can, but basically:
The context's HeapLayout is only "fixed" when all of the captures have
fixed type info. When the HeapLayout is fixed, then [the bindings]
need to map the context's fields to type parameters so that the
context destructor can find the metadata. When the HeapLayout is not
fixed, then the metadata is embedded in the context to be read
directly by the destructor, so there is not need to map captures to
type parameters--in this case, bypass computing the bindings because
it would fail when it sees ClassPointer or Metadata sources.
[I could have gotten this completely wrong, even after staring at the code for about an hour, so I think it's well worth explaining]
@atrick The issue is that we must not consider parameter sources as type sources (example: we can and do reconstruct type metadata T for a class reference parameter SomeClass in This is only an issue in non fixed heap layouts because only for those we need the metadata of non-fixed captures in the destructor. |
@aschwaighofer that makes perfect sense, but then why does this PR set |
"The issue is that we must not consider parameter sources as type sources..." It is only safe to There are two sources of type metadata: the ones passed explicitly to a generic function (or stored explicitly in the heap context), and those implicit in other parameters (e.g SomeClass parameter). We must ignore the SomeClass parameter source because it is not available in the destructor but only in the partial apply forwarder. All this is only an issue for non-fixed types because for fixed ones we don't need that Metadata. |
@aschwaighofer add that in a comment? Just doing a drive by. |
@gottesmm I'll include it in a follow up PR with other suggestions above |
@aschwaighofer thanks My confusion had to do with what the "bindings" for type metadata are
(I'm not actually sure what the comment about ClassPointer or Metadata |
With this all let values will be captured with in_guaranteed convention
by the closure. Following are the main changes :
SILGen changes:
in_guaranteed captures as per convention are consumed by the closure. And so SILGen should not generate a destroy_addr for an in_guaranteed capture.
But LetValueInitialization can push Dealloc and Release states of the captured arg in the Cleanup stack, and there is no way to access the CleanupHandle and disable the emission of destroy_addr while emitting the captures in SILGenFunction::emitCaptures.
So we now create, temporary allocation of the in_guaranteed capture iduring SILGenFunction::emitCaptures without emitting destroy_addr for it.
SILOptimizer changes:
IRGen changes :
The TypeMetadata of ClassPointSource kind sources are not populated in HeapLayout's NecessaryBindings. If we have a generic parameter on the HeapLayout which can be fulfilled by a ClassPointerSource, its TypeMetaData will not be found while constructing the dtor function of the HeapLayout.
So it is important to skip considering sources of ClassPointerSource kind, so that TypeMetadata of a dependent generic parameters gets populated in HeapLayout's NecessaryBindings.
rdar://58459539