[Openmcl-devel] Application bundles and the interface database

Gary Byers gb at clozure.com
Fri Oct 28 14:19:25 UTC 2005

On Fri, 28 Oct 2005, Tord Kallqvist Romstad wrote:

> Tord Kallqvist Romstad <romstad at math.uio.no> writes:
>> Gary Byers <gb at clozure.com> writes:

>>> Can you print the value of (FIND-CLASS 'NS:+NS-OBJECT) earlier in
>>> the .dfsl file (before the class definition ?)
>> Looks correct, doesn't it?
>> I don't know whether it has any significance, but I observe that the
>> hexadecimal number #xA28876FC, which appear when evaluating (FIND-CLASS
>> 'NS:+NS-OBJECT), is not equal to the number #xA28816FC, which appear
>> in the error message.
> After some further experiments, I think this *is* significant.  I
> tried compiling my application bundle on two Macs (an iMac G5 1.8 GHz
> and a G4 Cube 450 MHz, both running OS X 10.4.2).  It turns out that
> the bundle built on the iMac does not work on the Cube, and vice
> versa.
> When running the iMac-compiled bundle on the Cube, (FIND-CLASS
> 'NS:+NS-OBJECT+) evaluates to:
> while the error message reads:
>> Error: Class #<A Mac Pointer #xA28816FC> isn't recognized.
> When trying to run the Cube-compiled bundle on the iMac, I get exactly
> the opposite:

That's certainly suspicious.  As far as I know, #xA28816FC isn't
a class or metaclass object address in 10.4.2, and NS:+NS-OBJECT
seems to have addres #xA28876FC.  (The fact that there are only
a few bits' difference between these addresses is further grounds
for suspicion.)

>> Error: Class #<A Mac Pointer #xA28876FC> isn't recognized.
> -- 
> Tord Romstad

To try to explain what's (generally) going on here:

Most of the CLOS implementation assumes that a given class is only EQL
to itself (e.g., that EQL and EQ always return the same result when
both of their arguments are classes.)  Two MACPTRs that point to the
same address are EQL to each other but not necessarily EQ, so in order
to "fit" the idea of a pointer to an ObjC class being a CLOS class
into the CLOS implementation it's necessary to always use the same
MACPTR object to refer to a given class (and the same is true of ObjC
metaclasses.  If we get our hands on a pointer to an ObjC class or
metaclass - by doing a memory reference of some kind - we generally
have to find the canonical MACPTR that CLOS is using in order to perform
some CLOS operation.  (The "canonical" class or metaclass MACPTR is
EQL to the one we obtained from memory, but not unlikely to be EQ to it.)

The bridge maintains a couple of splay trees to keep track of information
about ObjC classes and metaclasses.  (A splay tree's just a special kind
of binary tree that reorganizes itself after a successful lookup, so
that frequently found keys tend to be nearer the root.)  The trees
use the class/metaclass pointers' addresses for comparison.

Those addresses and their relative ordering in memory can change (when
moving between OS releases and in other cases), so the splay trees are
supposed to be emptied by a function that runs just before
SAVB-APPLICATION saves the memory image.  (The function
CCL::%CLEAR-OBJC-CLASS-MAPS shold be on the list
CCL::*SAVE-EXIT-FUNCTIONS*.)  When the image starts up, the function
CCL::REVIVE-OBJC-CLASSES tries to find all of the ObjC classes that
had been known before the image was saved (which may now have different
addresses) and inserts them in the splay trees.

The error you're getting suggests that - shortly after
REVIVE-OBJC-CLASSES has allegedly done this - attempts to find
the class pointer for NS:+NS-OBJECT is failing.  The fact that you
can do (FIND-CLASS 'NS:+NS-OBJECT) - and print the result - suggests
that REVIVE-OBJC-CLASS has run and should have rebuilt the trees.
. well, I'm not entirely sure what it suggests.  I suppose that
it could mean that there's a bug in the tree-searching code, or that
the trees didn't get emptied during the SAVE-APPLICATION, or ...
something else that I'm not thinking of.

I've generally been able to run bundles saved on 10.3.x under 10.4.x
and vice versa, and haven't run into this sort of thing.

I'm not sure it it'd tell us anything, but if you do (in a dfsl file,
before you get the error)

(ccl::map-splay-tree (ccl::objc-metaclass-map)
                      #'(lambda (id) (print (ccl::id->objc-metaclass id))))

you should get around 300 lines of output, showing the "canonical"
ObjC metaclass pointers, sorted by address.  There shouldn't be any
duplicate class name or duplicate addresses in the printed output,
and the class NS:+NS-OBJECT should be in there.

I'm not sure that it's of general interest, but I'd be interested
in seeing that output.

More information about the Openmcl-devel mailing list