While in this case I can't think of any specific reasons beyond performance to need to implement objc_msgSend in assembly, there are absolutely instances where assembly is the only option.
Example: when performing a context switch in a kernel, assembly is required since C abstracts away architecture-specific details necessary to swap out the register set, swap the page directory pointer, etc.
My ObjC-fu is pretty old --- the last time I looked at it seriously was when poc was still a thing --- but my understanding is:
Traditionally objc_msgSend is in assembly because it doesn't know how many and what types the message parameters are. So it can't portably preserve them while it does the computations to find out where to send the message to.
This project's alternative obj_msgSend always passes parameters in a structure. That helps, because now you know that all message calls have three parameters; the destination object, the selector, and the parameter block.
However... they don't always pass the return value in the message block; instead it coerces any integer types to void* and returns them in the usual way, only using an extra field in the parameter block for those values which aren't coerceable to void.
This does make me kinda unhappy. I don't think* it'll be a problem, but... it's definitely pushing the limits of what C allows; round-tripping arbitrary integers through pointers is one of those things that's not technically allowed but all real-world compilers support, so, um. I'd much rather they just pass everything through the parameter block.
But yeah, it's a decent enough idea, which simplifies things considerably at not a lot of performance hit. I'm kind of surprised that ObjC doesn't already do that.
My main disappointment is that this is a clang variant and not a standalone preprocessor. Since poc died there isn't a working ObjC preprocessor, which means if you want to use ObjC you're limited to gcc or clang. An ObjC->C preprocessor would solve that.
I've been using arch for about 3 years and I think that things break just as often (actually, probably more often) and you're generally not left with a better sense of what the root cause is. Sure, you have less software installed, but you're also usually running bleeding-edge versions of everything and things are noticeably less stable.
I do think that from an educational standpoint, arch linux is a good OS to use, as you will probably get a lot more comfortable with the linux environment. This is largely out of necessity as you will spend a great deal of time setting up and fixing your system.
If you have the time to debug the various components of your system, it can be quite fun and educational to use, but if you're interested in getting work done I cannot recommend arch linux at all.
Huh, it seems people's experience varies a lot. I've been using Arch as my primary OS at work and home for something like 4 years now. It's been quite stable and low maintenance. It has broken a 3 or 4 times, but my Windows install that I play games on has broken more times than that.
Yeah, that's been my experience as well. I tried ubuntu first, and that broke every 6 months. Finally, a kernel upgrade rendered my system unusable, and I switched to Fedora once it was fixed. Fedora didn't break as much, but it still broke. Finally, I switched to Arch. I've been able to fix any breakage, and my system's been fine ever since.
I've never used Arch, although I've considered it. I was a Gentoo user for many years, and went through some breakage here and there. I finally went to Ubuntu and friends because it was cutting edge enough without the breakage that I've always experienced with cutting edge stuff. Even with the breakage from Gentoo, it was always much better than Windows, although windows has gotten much better since the Win95 days. I hardly have problems with Ubuntu, and I use mostly Xubuntu on my laptops.
I find it plenty usable for work. And because you're usually hand-writing the configs, it's much easier to root-cause than ubuntu. And it doesn't break every 6 months.
Very cool. I think that this is reflected in a lot of physical activities. From my personal experience with martial arts, I've definitely seen some (anecdotal) evidence to support the notion that you move more efficiently and correctly when you aren't thinking your way through it. It's cool to see some experimental support for this.
Every single program that your computer runs is nothing but a 'pile of bytes' that is carefully set up by your compiler. There is no technical reason that you cannot manually set up said byte piles and execute them, and it is actually not hard at all. (The only 'gotcha' is that some parts of memory are not marked as executable, but this can be changed at runtime or compile-time).
execve does nothing more than swap out which bytes are loaded into the address space of a program (okay, it does some other book-keeping too, but from 100 feet...). It is not necessary for continuing execution outside of what the program has set up at compile-time. In fact, you can dynamically generate code on the fly, as JIT compilers do.
Yes you can. An executable (using ELFs as an example, most formats are similar) is nothing more than some headers and bytes. The executable code can be modified in any way you please, as long as you're writing valid opcodes (the program will crash if it hits a bad opcode).
That said, it's usually much more complicated to change the size of the executable section (this requires modifying the headers and this tends to be a rather involved process), so usually if people are doing binary patches they are only modifying bytes, not adding or removing them.
His point was that you aren't interpreting the `const' the same way the compiler does.
To the compiler, this:
const int *a;
a = NULL; // perfectly OK
*a = 0; // does not compile
Is a pointer to a constant int, not a constant pointer to an int.
You're probably confusing it with this:
int *const a;
a = NULL; // does not compile
*a = 0; // perfectly OK
Which is a constant pointer to a regular int.
Of course you can combine both as follows:
const int *const a;
a = NULL; // does not compile
*a = 0; // does not compile
Which is a constant pointer to a constant int (which, of course, makes no sense at all in this case since 'a' is uninitialized and cannot be initialized without an unsafe cast, but it's a perfectly valid statement in C).
I think we're in violent disagreement. I fully understand what my code did, but people I've worked with and gone to school have been tripped up by statements like these. Stuff like this is all over exams.
> It's all about the underhanded trick(s) with the pointers, yours will never compile. I'm forcing clang to do horrible things.
Indicates, to me, that you see this as a strange behaviour that you're forcing the compiler into when in fact this is exactly the intended (and expected) semantics of const.
I was going to remark on this. I've personally run into this writing some C that was built on multiple platforms, one of which had c99 and one of which did not (c89 instead).
I think the real issue here is the inconsistency between C standards on details like this. If you can always assume that your code is built with c99 or later, then use all of its features, but in many cases that's not a realistic assumption.
“If there are fewer initializers in a list than there are members of an aggregate, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.”
If a scheduler change breaks userland apps, that sounds like a scheduler bug to me... Any word on whether there is going to be a rollback/further scheduler changes to make spinlocks useful again?
There will not. QOS was a very large and intentional change, and it's critical to getting great performance out of iOS and to make the fanless MacBook work at all.
In general, Apple has never encouraged anyone to use spinlocks, and as I mentioned at the end, as long as your critical section is really tiny and CPU-bound you're unlikely to actually have a problem in practice. Note that spinlocks have always had a problem with priority inversion (OSSpinLock's back-off algorithm is just to call syscall_thread_switch with a 1ms delay every 1024 iterations, which is not bad but doesn't solve all priority inversions anyway).
With a big bias towards "less". Dynamic linking on OS X uses strong binding (unless you specifically link your binaries with the option that disables strong binding). That is, symbols are associated with libraries. So for example, when your program wants the symbol for e.g. malloc, the symbol table will also have the information that the symbol is in libSystem.dylib (or whatever the lib for that is), and the dynamic linker will pick malloc from there, even when DYLD_INSERT_LIBRARIES contains a library exporting the malloc symbol.
On GNU/Linux at least, even with symbol versioning, which adds some binding information linking symbol version names to library names, ld.so still resolves symbols with versions to the symbol exported by a library in LD_PRELOAD.
Example: when performing a context switch in a kernel, assembly is required since C abstracts away architecture-specific details necessary to swap out the register set, swap the page directory pointer, etc.