This is an archive of the discontinued LLVM Phabricator instance.

[CodeGen] Treat ObjC `__unsafe_unretained` and class types as trivial when generating copy/dispose helper functions
ClosedPublic

Authored by ahatanak on Jan 10 2022, 8:18 AM.

Details

Summary

Analyze the block captures just once before generating copy/dispose block helper functions and honor the inert __unsafe_unretained qualifier. This refactor fixes a bug where captures of ObjC __unsafe_unretained and class types were needlessly retained/released by the copy/dispose helper functions.

Diff Detail

Event Timeline

ahatanak created this revision.Jan 10 2022, 8:18 AM
ahatanak requested review of this revision.Jan 10 2022, 8:18 AM
rjmccall added inline comments.Jan 10 2022, 12:30 PM
clang/lib/CodeGen/CGBlocks.cpp
41

Does this actually work? It's a hashtable, so I'm worried about the possibility of e.g. a bad set of collisions causing it to grow. Even if it works today, it seems like a dangerous assumption to make.

If we're going to make SortedCaptures stick around, is there any way we can keep the Capture objects there and then have Captures just store pointers into it? We'd just have to build Captures after the sorting was complete; I don't know if that's possible.

clang/lib/CodeGen/CGBlocks.h
248

Please explain what this means in a comment — it's just whether the whole block itself is noescape, right?

ahatanak updated this revision to Diff 398800.Jan 10 2022, 6:35 PM
ahatanak marked 2 inline comments as done.

Build the map (Captures) after building the vector (SortedCaptures).

Also fix a minor bug where a BlockLayoutChunk wasn't being removed after being copied when the end of the header wasn't aligned (see test6 in CodeGenObjC/blocks.m), which was needed since CodeGenObjC/arc-captured-32bit-block-var-layout-2.m started failing after applying this patch.

rjmccall added inline comments.Jan 10 2022, 7:38 PM
clang/lib/CodeGen/CGBlocks.cpp
360–361

"byref"

1954

Should this be specific to whether this is trivial to copy?

2143

Should this condition be specific to whether it's trivial *to destroy*? C++ types could be trivial to destroy but not to copy (and, theoretically, vice-versa).

clang/lib/CodeGen/CGBlocks.h
267–268

This comment is out-of-date, and it should also be updated to say that the values are pointers into SortedCaptures.

305

We can use auto now, and this seems like a good place for it.

ahatanak added inline comments.Jan 10 2022, 8:02 PM
clang/lib/CodeGen/CGBlocks.cpp
2143

Adding the check here won't change anything since pushCaptureCleanup is a no-op if the type is trivial to destroy. But we can replace NeedsCopyDispose with NeedsCopy and NeedsDispose so that we can track whether copy and dispose helpers are needed separately and avoid emitting empty dispose helper functions.

I'm not sure whether we should do that in this patch or in another patch.

rjmccall added inline comments.Jan 10 2022, 8:44 PM
clang/lib/CodeGen/CGBlocks.cpp
2143

Technically, it would save emitting a GEP, but I agree that that's probably not worth thinking about, so nevermind.

Avoiding emitting the functions is probably best to do in a separate patch. The runtime does allow null pointers here even if the descriptor says that the helpers exist?

ahatanak added inline comments.Jan 10 2022, 9:20 PM
clang/lib/CodeGen/CGBlocks.cpp
2143

Yes, the runtime checks whether the copy/dispose helper function field is null before calling the function.

ahatanak updated this revision to Diff 398948.Jan 11 2022, 7:40 AM
ahatanak marked 3 inline comments as done.

Update comments.

rjmccall accepted this revision.Jan 11 2022, 10:58 AM

Thanks, LGTM

This revision is now accepted and ready to land.Jan 11 2022, 10:58 AM