gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ABI Compatibility (was Re: Installation woes for the average user...


From: David Chisnall
Subject: Re: ABI Compatibility (was Re: Installation woes for the average user...)
Date: Tue, 10 Mar 2009 13:14:09 +0000

On 10 Mar 2009, at 10:28, Xavier Glattard wrote:


Riccardo Mottola a écrit :
(...)
David Chisnall wrote:
(...)
Yes, this appears to me the "least hurting" path. But I laready dislike.
If we really need, this should be the road.
If you make private ivars into a structure and make a pointer to this an ivar, you add an extra malloc for every +alloc (expensive) and you
add an extra load for ever ivar access.
That is an abomination.

Another stupid question : the memory allocation function accepts an 'extraBytes' parameter. These bytes are allocated _after_ the instance bytes by the same 'malloc' call. Couldn't this system be adapted to ivar storage ? The extra storage is at self+1 : no need for an additional pointer, and no extra load for ivar access.

The extra bytes are allocated after the object, which would be completely useless. Imagine:

Class A has 1 int ivar a..
Class B subclasses A and adds another int ivar b.

The layout of B will be:

        id isa; // offset 0
        int a;  // offset 4
        int b;  // offset 8

Now you use the extrabytes feature to add space for another int, so you have:

        id isa; // offset 0
        int a;  // offset 4
        int b;  // offset 8
        int extra;      // offset 12

Now you add another ivar to A and remove the extra bytes, and you have this layout:

        id isa; // offset 0
        int a;  // offset 4
        int a1; // offset 8
int b; // offset 12 <- This has now moved and class B needs recompiling, as do any subclasses of B.

Alternatively, you could try storing the data in the extra bytes, so the layout would be:

        id isa; // offset 0
        int a;  // offset 4
        int b;  // offset 8
        int a1; // offset 12

That sounds sensible, unless you remember that there may be other subclasses of A. Imagine subclass C declares two doubles as ivars. Now you have three classes:

A:
        id isa; // offset 0
        int a;  // offset 4
        int a1; // offset 8

B:
        id isa; // offset 0
        int a;  // offset 4
        int b;  // offset 8
        int a1; // offset 12

C:
        id isa; // offset 0
        int a;  // offset 4
        double c1;      // offset 8
        double c2;      // offset 16
        int a1; // offset 24

We now have three different classes, with offsets of 8, 12 and 24, respectively for the a1 ivar. Every method that attempted to access this ivar would need to determine which class it is and calculate the offset. This would need a macro like this:

#define a1 (*((int*)(((char*)self) +isa->instance_size)))

This would be really horrible and error-prone (this macro doesn't take into account alignment, so is only valid for architectures like x86, with no strict alignment requirements (as long as none of the ivars are vectors), and would break on SPARC and similar archs. The next ivar you add would need an even more complex macro to account for the alignment of a1. This ivar would not be exposed via any introspection, so you couldn't use it with KVC/KVO, bindings, or EtoileUI without writing even more code.

In short, this adds a lot more problems than it solves. The extra storage is not at self+1 unless self is cast to the correct subclass first. Pointer arithmetic like that only works when the size of the pointee is known at compile time, which is not the case for Objective- C objects, except in the trivial case of classes with no subclasses, which do not encounter this problem to start with.

David



reply via email to

[Prev in Thread] Current Thread [Next in Thread]