[Openmcl-devel] Missing header(s) for OpenGL FFI?

Gary Byers gb at clozure.com
Sat Aug 12 14:49:27 PDT 2006

On Sat, 12 Aug 2006, Phil wrote:

> So it sounds like for the time being the workaround is to revert to the old 
> interfaces until a fix is available?
> I know very little about the Obj-C runtime and less about how the bridge 
> works under the covers so I'm preparing to duck after asking this naive 
> question ;-)  Is it not possible to query the Obj-C runtime itself with the 
> pointer and let it tell OpenMCL whether the pointer is something it knows 
> about and, if so, what it is?

That's basically what happens, but if you just have some random pointer
that might be pointing to un-mapped memory, you'll segfault trying to
determine whether it's an ObjC object or not.

Another approach to this is to just tell the segfault handler (somehow)
that a segfault isn't totally unexpected.  If we have a pointer P that
-might- be an ObjC instance, what we want to know if whether

  (known-objc-class-p (pref p :objc_object.isa))

e.g., whether the "isa" field of that (alleged) ObjC object denotes
a known ObjC class.  The problem is that that PREF (which just macroexpands
into %GET-PTR) will crash if P is pointing off into the ozone (unmapped
memory), and the scheme has been to try and precede that PREF with some
other checks (was P allocated my #_malloc, or is it in the data segment
of some library that might contain NSConstantString instances or similar
static NSObjects),  Both the #_malloc check and the binary search are
fairly expensive, and that's a lot to pay if (most of the time) the
random pointer either (a) clearly points to unmapped memory (is a
null pointer) or (b) probably points to mapped memory and may or may
not really be an ObjC object.

If there was something like SAFE-PREF - that told the exception-handling
code in the lisp kernel that a segfault was possible but non-fatal, and
it should just skip over the memory reference and return 0 (easy on PPC,
maybe harder on x86-64) in that case - well, that might be better and
generally faster than the heuristics.

In the short term, I'll try to just see what's wrong with the binary
search; it can't be that hard to get right (famous last words.)

> On Aug 12, 2006, at 3:00 PM, Gary Byers wrote:
>> Someone somewhere once said that "simple binary search" is never simple.
>> Or something like that.
>> The way that the bridge usually tries to determine whether or not a
>> random pointer is or is not an instance of some ObjC class is to
>> ask #_malloc for information about the memory region where the pointer
>> is allocated; if #_malloc knows about the pointer, then the bridge
>> looks to see if the first word in the pointer references an ObjC class.
>> (The #_malloc check is basically there to ensure that the pointer
>> points to mapped memory and that we won't segfault when trying to
>> look at its first word.)  The check's obviously a little slow, but
>> information about the results of the check are cached in bits in
>> the pointer object, so it's only done at most once per (EQ) unique
>> pointer.
>> Unfortunately, that isn't adequate to recognize all instances of
>> NSConstantString and related (CF) classes, which are often just
>> embedded in the data segments of libraries.  The bridge tries to keep
>> track of the memory regions associated with all known shared
>> libraries, and does a binary search through that list of regions to
>> see if a given pointer is contained within any of them.  (If so, it's
>> safe to indirect through the pointer and look at its first word, and
>> that first word -might- reference a class like NSConstantString, in
>> which case the pointer will be recognized as an instance of that class.)
>> (At one point a couple of years ago, the binary search was a linear
>> search and was naturally even slower.  There are a finite number
>> of NSConstantString instances in all loaded libraries at any given
>> time, and I think that it'd be possible to enumerate them by looking
>> at relocation information and make it much easier to recognize these
>> instances.)
>> Anyway, the short version is that there's a bug in that binary search
>> code that makes it impossible to determine the class of some pointers-to-
>> possible-ObjC-objects.  Presumably, the recursive error failure has 
>> something
>> to do with trying to print an object whose class can't be determined 
>> without
>> signalling an error.
>> It may be the case that there appears to be nothing different between
>> the environment where the error occurs and the environment where it
>> doesn't besides the set of interfaces in use, but I'd guess that (for
>> some reason) either a slightly different set of shared libraries is
>> loaded or (for some reason) they're mapped at slightly different addresses,
>> and one or the other of these differences is enough to trigger the 
>> fencepost
>> in the binary search routine (CCL::POINTER-IN-CFSTRING-SECTION-P).
>> I thought that I'd fixed the real (fencepost) problem at some point (and
>> I'm pretty sure that I remember that it was a fencepost problem in
>> that binary search routine, which is of course so simple that it's
>> impossible to get right ...), but if I remember that correctly it
>> doesn't look like I checked the fix in.
>> The runtime doesn't expect CLASS-OF to fail; that's a generally
>> reasonable assumption, but the fact that it is failing seems to
>> be what's causing the error death-spiral.

More information about the Openmcl-devel mailing list