-
Notifications
You must be signed in to change notification settings - Fork 10.5k
IRGen: properly handle deallocation of a boxed type #12717
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
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// RUN: %target-swift-frontend -primary-file %s -emit-ir -o - | %FileCheck %s | ||
|
||
func f() -> Bool? { return nil } | ||
|
||
({ | ||
guard var b = f() else { return } | ||
let c = { b = true } | ||
_ = (b, c) | ||
})() | ||
|
||
// CHECK-LABEL: @_T09alloc_boxyycfU_ | ||
// CHECK: <label>:8: | ||
// CHECK: call void @swift_setDeallocating | ||
// CHECK: call void @swift_rt_swift_deallocObject | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
We call
boxTI.deallocate()
from thedealloc_box
SIL instruction. It assumes that the box object is uninitialized.emitDeallocateHeapObject assumes that an object is in the deallocating stage -- we need to mark it as such. Under a normal lifetime of an object this is done by the ultimate release. Since we forgo the ultimate release here (the object is unitialized) marking it as deallocating (setting the IsDeallocating bit) is correct.
This LGTM.
I believe we also need this call inside the NonFixedBoxTypeInfo deallocate method because swift_deallocBox also directly calls swift_deallocObject.
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.
Should SILGen be emitting a
set_deallocating
instruction somewhere instead?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 believe this is valid SIL:
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.
@aschwaighofer I think that we want to do the
NonFixedBoxTypeInfo
in a separate change (happy to take that on, though need to figure out a test case for that), but I believe that you are right that this needs to be mirrored there as well.@jckarter that was exactly my question when I started investigating this. Given a quick skim of the SIL langref, I came to the conclusion that the sample that @aschwaighofer posted was desired and that we should handle this by emitting the call in the deallocate handling.
Thanks for the review @aschwaighofer! Going to merge this for now, and follow up with a change for the
NonFixedBoxTypeInfo
case.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.
@jckarter pointed out that calling a runtime function is overhead.
We only check this in assert builds. Can you conditionalize the call to
IGF.emitNativeSetDeallocating(box);
on assert builds?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 agree with @gparker42 that the assertions are invaluable debugging assets. So, I was looking at this a bit further for the
NonFixedBoxTypeInfo
. I think my understanding might be too weak to come up with a proper test case for that. I was trying to play with returning an optional protocol instead of a concrete type (AIUI which should give us a non-fixed sized boxed type), however, that seems to work properly. I believe that the reasoning for that is that we are constructing the indirect destruction, which will correctly mark up theDeiniting
bit on the object. I think that the problem is as @jckarter pointed out: we are directly callingswift_deallocObject
, and that does not guarantee that the object is in the right state for the tear down. Doing the forced deallocation as a flag sounds like a reasonable approach to avoiding the extra runtime call. At that point, this seems like it may tread into the ABI breaking territory, so we should figure this out and implement it before the 5.0 release.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.
Here is an example for NonFixedTypes.
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 checked and it is necessary to set the bit i.e. the solution to just skip the check is not valid.
If we don't set the bit we end up on the
swift_unownedRelease
path in swift_deallocObject:It needs class metadata:
We should just add an entry point that is a combination of
swift_setDeallocating
andswift_deallocObject
and call it instead ofemitDeallocateHeapObject
.swift_deallocBox
should callobject->refCounts.decrementFromOne
(equivalent to callingswift_setDeallocting
).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 latter: #12744
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 former: #12745