From: Christophe R. <cs...@ca...> - 2003-03-29 10:59:53
|
ger...@t-... (Gerd Moellmann) writes: > Christophe Rhodes <cs...@ca...> writes: >> -- oh, and why INSTANCE isn't on the superclass list for >> STANDARD-OBJECT any more... > > It can't, because GENERIC-FUNCTION is a subclass of STANDARD-OBJECT, > and at the same time generic functions need to be funcallable > instances. > >> why isn't this breaking things that expect to have instances as type >> specifiers?) > > Could you explain? OK, here is my essential problem, but it shows up elsewhere, too: ;;; FIXME: The SB!KERNEL:INSTANCE here really means CL:CLASS. ;;; However, the CL:CLASS type is only defined once PCL is loaded, ;;; which is before this is evaluated. Once PCL is moved into cold ;;; init, this might be fixable. (sb!xc:deftype type-specifier () '(or list symbol sb!kernel:instance)) [ from sbcl's src/code/deftypes-for-target ] Now, in an SBCL with the patch to restore METAOBJECT, and remove INSTANCE from the superclass list of STANDARD-OBJECT: (typep (find-class 'integer) 'sb-kernel:instance) -> NIL So naively, one might expect that one couldn't use classes as type specifiers any more; however, this is not the case: (typep 1 (find-class 'integer)) -> T Despite the fact that TYPEP doesn't think that a class is an INSTANCE, the class is getting through without being treated as a type error. The reason for this is that the mechanism for compiled code is different: instead of inspecting the class hierarchy completely, a test for SB-KERNEL:INSTANCEness is simply compiled to a LOWTAG test. (funcall (lambda (x) (typep x 'sb-kernel:instance)) (find-class 'integer)) -> T (sb-kernel:%instancep (find-class 'integer)) -> T (= (sb-kernel:lowtag-of (find-class 'integer)) sb-vm:instance-pointer-lowtag) -> T This kind of discrepancy is bad. It's the kind of thing that leads to sucky scary bugs in two years' time when someone finally wrestles PCL into the main system and starts to use it, when differences between interpreted/full-class and compiled calls are likely to become important. Potential solutions: I don't really have that many, actually. One way is to ignore the requirement in AMOP for a METAOBJECT class and for FUNCALLABLE-STANDARD-OBJECT to be a subclass of STANDARD-OBJECT. This is far from ideal, I grant, but... another way would be to make the layouts for INSTANCE and FUNCTION compatible. This has potential performance ramifications, though, in that everywhere that previously did just a simple lowtag test for functionness would probably have to do both a lowtag and a widetag test (the implementation I have in mind would (ab)use the fact that INSTANCE- and FUNCTION-POINTER-LOWTAG are four apart, so the new FUNCTIONP would be something like: and <lowtag>, 3 cmp <lowtag>, 1 ; = (logand {instance,function}-pointer-lowtag 3) jne ERROR_NOT_FUNCALLABLE [load widetag] cmp <widetag>, FUNCTION_MASK which is perhaps too radical a slowdown, I dunno. Do you see the essential problem, though? Cheers, Christophe -- http://www-jcsu.jesus.cam.ac.uk/~csr21/ +44 1223 510 299/+44 7729 383 757 (set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b))) (defvar b "~&Just another Lisp hacker~%") (pprint #36rJesusCollegeCambridge) |