Skip to content
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

Implement __attribute__((objc_direct)), __attribute__((objc_direct_me… #328

Merged

Conversation

MadCoder
Copy link

…mbers))

attribute((objc_direct)) is an attribute on methods declaration, and
attribute((objc_direct_members)) on implementation, categories or
extensions.

A direct property specifier is added (@Property(direct) type name)

These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.

The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.

The implicit self and _cmd arguments are preserved, however to
maintain compatibility with the usual objc_msgSend semantics,
3 fundamental precautions are taken:

  1. for instance methods, self is nil-checked. On arm64 backends this
    typically adds a single instruction (cbz x0, ) to the
    codegen, for the vast majority of the cases when the return type is a
    scalar.

  2. for class methods, because the class may not be realized/initialized
    yet, a call to [self self] is emitted. When the proper deployment
    target is used, this is optimized to objc_opt_self(self).

    However, long term we might want to emit something better that the
    optimizer can reason about. When inlining kicks in, these calls
    aren't optimized away as the optimizer has no idea that a single call
    is really necessary.

  3. the calling convention for the _cmd argument is changed: the caller
    leaves the second argument to the call undefined, and the selector is
    loaded inside the body when it's referenced only.

As far as error reporting goes, the compiler refuses:

  • making any overloads direct,
  • making an overload of a direct method,
  • implementations marked as direct when the declaration in the
    interface isn't (the other way around is allowed, as the direct
    attribute is inherited from the declaration),
  • marking methods required for protocol conformance as direct,
  • messaging an unqualified id with a direct method,
  • forming any @selector() expression with only direct selectors.

As warnings:

  • any inconsistency of direct-related calling convention when
    @selector() or messaging is used,
  • forming any @selector() expression with a possibly direct selector.

Lastly an objc_direct_members attribute is added that can decorate
@implementation blocks and causes methods only declared there (and in
no @interface) to be automatically direct. When decorating an
@interface then all methods and properties declared in this block are
marked direct.

Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall

…mbers))

__attribute__((objc_direct)) is an attribute on methods declaration, and
__attribute__((objc_direct_members)) on implementation, categories or
extensions.

A `direct` property specifier is added (@Property(direct) type name)

These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.

The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.

The implicit `self` and `_cmd` arguments are preserved, however to
maintain compatibility with the usual `objc_msgSend` semantics,
3 fundamental precautions are taken:

1) for instance methods, `self` is nil-checked. On arm64 backends this
   typically adds a single instruction (cbz x0, <closest-ret>) to the
   codegen, for the vast majority of the cases when the return type is a
   scalar.

2) for class methods, because the class may not be realized/initialized
   yet, a call to `[self self]` is emitted. When the proper deployment
   target is used, this is optimized to `objc_opt_self(self)`.

   However, long term we might want to emit something better that the
   optimizer can reason about. When inlining kicks in, these calls
   aren't optimized away as the optimizer has no idea that a single call
   is really necessary.

3) the calling convention for the `_cmd` argument is changed: the caller
   leaves the second argument to the call undefined, and the selector is
   loaded inside the body when it's referenced only.

As far as error reporting goes, the compiler refuses:
- making any overloads direct,
- making an overload of a direct method,
- implementations marked as direct when the declaration in the
  interface isn't (the other way around is allowed, as the direct
  attribute is inherited from the declaration),
- marking methods required for protocol conformance as direct,
- messaging an unqualified `id` with a direct method,
- forming any @selector() expression with only direct selectors.

As warnings:
- any inconsistency of direct-related calling convention when
  @selector() or messaging is used,
- forming any @selector() expression with a possibly direct selector.

Lastly an `objc_direct_members` attribute is added that can decorate
`@implementation` blocks and causes methods only declared there (and in
no `@interface`) to be automatically direct. When decorating an
`@interface` then all methods and properties declared in this block are
marked direct.

Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall
@MadCoder
Copy link
Author

@swift-ci please test

@hyp hyp self-requested a review November 18, 2019 23:53
Copy link

@hyp hyp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dexonsmith dexonsmith merged commit d976623 into swiftlang:apple/stable/20191106 Nov 19, 2019
@MadCoder MadCoder deleted the eng/PR-2684889-direct branch November 19, 2019 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants