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

objc_direct methods #165

Closed
digital-pers0n opened this issue Jul 2, 2020 · 4 comments · Fixed by #268
Closed

objc_direct methods #165

digital-pers0n opened this issue Jul 2, 2020 · 4 comments · Fixed by #268
Assignees

Comments

@digital-pers0n
Copy link

GNU runtime doesn't support direct calls at this time
Aren't they just simple C-functions?

@davidchisnall davidchisnall self-assigned this Jul 2, 2020
@davidchisnall
Copy link
Member

Not quite. They also need to ensure that the +initialize method is invoked. There's a comment in the Mac version that describes some of this:

  // Generate:
  //
  // /* for class methods only to force class lazy initialization */
  // self = [self self];
  //
  // /* unless the receiver is never NULL */
  // if (self == nil) {
  //     return (ReturnType){ };
  // }
  //
  // _cmd = @selector(...)

I think this is actually wrong, because if you do objc_allocateInstance and then send it a message, it won't call +initialize and they've broken the language semantics.

@davidchisnall
Copy link
Member

I don't really like requiring a message send here, because it largely defeats the point of direct messages for efficiency. I'm tempted to add an __objc_initialize function to guarantee that +initialize has been called. I'm also tempted to make the caller responsible for calling it - if a static method is called from within another method on the same class (or a subclass) it can be elided, and a little bit of analysis should allow it to be elided elsewhere as well.

@digital-pers0n
Copy link
Author

Looks like they know about this problem.
several entry points for direct methods
unnecessary class initialization in direct methods
Also in the recent Apple's objc runtime there are new runtime functions to bypass objc_msgSend for rarely overridden methods
such as self, new, class, isKindOfClass and respondsToSelector the functions are prefixed with objc_opt_* NSObject.mm

@davidchisnall
Copy link
Member

It looks as if the code for the objc_opt_ stuff is not in the public LLVM, only in Apple's fork.

davidchisnall added a commit that referenced this issue Jan 7, 2024
The fast paths follow the pattern that we established for fast ARC:
Framework base classes can opt in by implementing a `+_TrivialAllocInit`
method.

This opt-in behaviour is inherited and is removed implicitly in any
subclass that implements alloc or init methods (alloc and init are
treated independently).

Compilers can emit calls to `objc_alloc(cls)` instead of `[cls alloc]`,
`objc_allocWithZone(cls)` instead of `[cls allocWithZone: NULL]`, and
`objc_alloc_init` instead of `[[cls alloc] init]`.

Direct methods don't require very much support in the runtime.  Apple
reuses their fast path for `-self` (which is supported only in the Apple
fork of clang, not the upstream version) for a fast init.  Given that
the first few fields of the runtime's class structure have been stable
for around 30 years, I'm happy moving the flags word (and the
initialised bit, in particular) into the public ABI.  This lets us do a
fast-path check for whether a class is initialised in class methods and
call `objc_send_initialize` if it isn't.  This function is now exposed
as part of the public ABI, it was there already and does the relevant
checks without invoking any of the message-sending machinery.

Fixes #165 #169
davidchisnall added a commit that referenced this issue Jan 13, 2024
The fast paths follow the pattern that we established for fast ARC:
Framework base classes can opt in by implementing a `+_TrivialAllocInit`
method.

This opt-in behaviour is inherited and is removed implicitly in any
subclass that implements alloc or init methods (alloc and init are
treated independently).

Compilers can emit calls to `objc_alloc(cls)` instead of `[cls alloc]`,
`objc_allocWithZone(cls)` instead of `[cls allocWithZone: NULL]`, and
`objc_alloc_init` instead of `[[cls alloc] init]`.

Direct methods don't require very much support in the runtime.  Apple
reuses their fast path for `-self` (which is supported only in the Apple
fork of clang, not the upstream version) for a fast init.  Given that
the first few fields of the runtime's class structure have been stable
for around 30 years, I'm happy moving the flags word (and the
initialised bit, in particular) into the public ABI.  This lets us do a
fast-path check for whether a class is initialised in class methods and
call `objc_send_initialize` if it isn't.  This function is now exposed
as part of the public ABI, it was there already and does the relevant
checks without invoking any of the message-sending machinery.

Fixes #165 #169
davidchisnall added a commit that referenced this issue Jan 13, 2024
The fast paths follow the pattern that we established for fast ARC:
Framework base classes can opt in by implementing a `+_TrivialAllocInit`
method.

This opt-in behaviour is inherited and is removed implicitly in any
subclass that implements alloc or init methods (alloc and init are
treated independently).

Compilers can emit calls to `objc_alloc(cls)` instead of `[cls alloc]`,
`objc_allocWithZone(cls)` instead of `[cls allocWithZone: NULL]`, and
`objc_alloc_init` instead of `[[cls alloc] init]`.

Direct methods don't require very much support in the runtime.  Apple
reuses their fast path for `-self` (which is supported only in the Apple
fork of clang, not the upstream version) for a fast init.  Given that
the first few fields of the runtime's class structure have been stable
for around 30 years, I'm happy moving the flags word (and the
initialised bit, in particular) into the public ABI.  This lets us do a
fast-path check for whether a class is initialised in class methods and
call `objc_send_initialize` if it isn't.  This function is now exposed
as part of the public ABI, it was there already and does the relevant
checks without invoking any of the message-sending machinery.

Fixes #165 #169
davidchisnall added a commit that referenced this issue Jan 13, 2024
The fast paths follow the pattern that we established for fast ARC:
Framework base classes can opt in by implementing a `+_TrivialAllocInit`
method.

This opt-in behaviour is inherited and is removed implicitly in any
subclass that implements alloc or init methods (alloc and init are
treated independently).

Compilers can emit calls to `objc_alloc(cls)` instead of `[cls alloc]`,
`objc_allocWithZone(cls)` instead of `[cls allocWithZone: NULL]`, and
`objc_alloc_init` instead of `[[cls alloc] init]`.

Direct methods don't require very much support in the runtime.  Apple
reuses their fast path for `-self` (which is supported only in the Apple
fork of clang, not the upstream version) for a fast init.  Given that
the first few fields of the runtime's class structure have been stable
for around 30 years, I'm happy moving the flags word (and the
initialised bit, in particular) into the public ABI.  This lets us do a
fast-path check for whether a class is initialised in class methods and
call `objc_send_initialize` if it isn't.  This function is now exposed
as part of the public ABI, it was there already and does the relevant
checks without invoking any of the message-sending machinery.

Fixes #165 #169
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants