From: Gerd M. <ger...@t-...> - 2003-03-28 16:59:46
|
I've just comitted fixes for breaking vicious circles that PCL can enter when adding subclasses to classes like STANDARD-METHOD. There was an example on cmucl-help recently. You have anon CVS access again, or should I send you diffs? |
From: Christophe R. <cs...@ca...> - 2003-03-28 19:09:15
|
Gerd Moellmann <ger...@t-...> writes: > I've just comitted fixes for breaking vicious circles that PCL can > enter when adding subclasses to classes like STANDARD-METHOD. There > was an example on cmucl-help recently. > > You have anon CVS access again, or should I send you diffs? We have anon cvs, thanks. (BTW, I have booted your METAOBJECT diff, and it seems to work about as well as before. Now I'm just confused about the presence of STD-CLASS -- oh, and why INSTANCE isn't on the superclass list for STANDARD-OBJECT any more... why isn't this breaking things that expect to have instances as type specifiers?) I wonder vaguely if it might be worth creating a portable-pcl list much as there's a portable-clx? Probably the overhead is too great in this, though the OpenMCL folks were thinking of looking at PCL for their clos recently. 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) |
From: <ger...@t-...> - 2003-03-28 19:25:04
|
Christophe Rhodes <cs...@ca...> writes: > We have anon cvs, thanks. (BTW, I have booted your METAOBJECT diff, > and it seems to work about as well as before. About as? ;) > Now I'm just confused about the presence of STD-CLASS STD-CLASS is already in early PCLs; its comment says "an implementation-specific common superclass of STANDARD-CLASS and FUNCALLABLE-STANDARD-CLASS". It's certainly convenient to have in the implementation, see some of its uses. > -- 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? > I wonder vaguely if it might be worth creating a portable-pcl list > much as there's a portable-clx? Probably the overhead is too great in > this, I tend to agree. > though the OpenMCL folks were thinking of looking at PCL for their > clos recently. Hm :-|. |
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) |
From: <ger...@t-...> - 2003-03-29 13:47:01
|
Christophe Rhodes <cs...@ca...> writes: > Do you see the essential problem, though? Yes, please let me think about it a bit. |
From: <ger...@t-...> - 2003-03-29 15:25:46
|
Christophe Rhodes <cs...@ca...> writes: > Potential solutions: [...] Hm. (defclass standard-object (slot-object kernel:instance) ()) (typep (find-class 'integer) 'instance) => t Doesn't look bad. OK, I admit it. I've hacked UPDATE-LISP-CLASS-LAYOUT. I wonder if that or something like it isn't the best/easiest way to get out of this trouble. What I was thinking is basically: Every CLOS object is an INSTANCE, except when it is a FUNCALLABLE-INSTANCE. We can express the first by making INSTANCE a superclass of STANDARD-OBJECT, but we can't directly express the "except" part, we can only add the FUNCALLABLE-INSTANCE superclass for funcallable objects. Thus the change UPDATE-LISP-CLASS-LAYOUT implementing the "except" part by removing INSTANCE if it's really a FUNCALLABLE-INSTANCE. I'd think this makes the kernel happy because the layouts should now reflect reality. What do you think? |
From: Christophe R. <cs...@ca...> - 2003-03-29 15:48:01
|
ger...@t-... (Gerd Moellmann) writes: > (defclass standard-object (slot-object kernel:instance) ()) > > (typep (find-class 'integer) 'instance) > => t > > Doesn't look bad. > > OK, I admit it. I've hacked UPDATE-LISP-CLASS-LAYOUT. Brave man. (candidate for a renaming, that one, to UPDATE-KERNEL-CLASS-LAYOUT [ or in our case, UPDATE-CLASSOID-LAYOUT ] is it not? :-) > I wonder if that or something like it isn't the best/easiest way to > get out of this trouble. You might be right. As you might have detected, I wasn't happy with either of my potential solutions. Certainly, having a clear low-level distinction between "objects that are funcallable" and "objects that aren't funcallable" is reasonable, and this distinction is almost but not quite the same as "objects that are opaque" and "objects whose slots we need to be able to reason about", the difficulty being inside the FUNCALLABLE-INSTANCE regime. Even without looking at your solution, I can tell that it's what the SBCL source code would call a KLUDGE, but I've now been thinking about this for about 12 hours (OK, so I was asleep for some of those, but some of my best ideas... :-) and I think that there will always be a kludge at a fundamental level, because we do have to tie these fundamentally different things together. At least, the only way I can see to make a clean solution is to do surgery on the LAYOUT assumptions, and I'm not that foolish^Wbrave. > [...] Thus the change UPDATE-LISP-CLASS-LAYOUT implementing the > "except" part by removing INSTANCE if it's really a > FUNCALLABLE-INSTANCE. > > I'd think this makes the kernel happy because the layouts should > now reflect reality. > > What do you think? So, just to make sure that I've understood what you're proposing, the PCL fundamental classes are something like (defclass standard-object (slot-object instance) ()) (defclass funcallable-standard-object (standard-object funcallable-instance) ()) and the KERNEL::CLASS (renamed it yet? ;-) associated with FUNCALLABLE-STANDARD-OBJECT does not have KERNEL:INSTANCE among its superclasses? If there is a way to have the PCL and kernel class hierarchies agree, as well as the type system, that would be my preference, even if it means a slightly more invasive coupling or a slightly more kludgey braid; if I understand it correctly, what you're proposing would make the kernel class hierarchy agree with the type tags, but not with the PCL hierarchy? I guess that's not so bad, if that's where you want to leave it. Does that make sense? 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) |
From: <ger...@t-...> - 2003-03-29 16:25:37
|
Christophe Rhodes <cs...@ca...> writes: > > OK, I admit it. I've hacked UPDATE-LISP-CLASS-LAYOUT. > > Brave man. (candidate for a renaming, that one, to > UPDATE-KERNEL-CLASS-LAYOUT [ or in our case, UPDATE-CLASSOID-LAYOUT ] > is it not? :-) Hm, CLASSOID, hmhm, bah ;). > > I wonder if that or something like it isn't the best/easiest way to > > get out of this trouble. > > You might be right. As you might have detected, I wasn't happy with > either of my potential solutions. Certainly, having a clear low-level > distinction between "objects that are funcallable" and "objects that > aren't funcallable" is reasonable, and this distinction is almost but > not quite the same as "objects that are opaque" and "objects whose > slots we need to be able to reason about", the difficulty being inside > the FUNCALLABLE-INSTANCE regime. > > Even without looking at your solution, I can tell that it's what the > SBCL source code would call a KLUDGE, Isn't all of PCL one big, gigantic, enormous kludge of sorts? In that way, fuzzing with layouts fits in very well :). BTW, thinking of kludges, I found I never before read Appendix C of AMOP, "Living with Circularity". It's worth having a look at it :). [...] > So, just to make sure that I've understood what you're proposing, the > PCL fundamental classes are something like > (defclass standard-object (slot-object instance) ()) > (defclass funcallable-standard-object (standard-object > funcallable-instance) ()) Yup. > and the KERNEL::CLASS (renamed it yet? ;-) Tomorrow, after I've committed my EVAL-WHEN hacks that redirect compile-time side effects when compiling CMUCL. It will be easier then ;). > associated with FUNCALLABLE-STANDARD-OBJECT does not have > KERNEL:INSTANCE among its superclasses? That should be the case, I think. > If there is a way to have the PCL and kernel class hierarchies agree, > as well as the type system, that would be my preference, even if it > means a slightly more invasive coupling or a slightly more kludgey > braid; if I understand it correctly, what you're proposing would make > the kernel class hierarchy agree with the type tags, but not with the > PCL hierarchy? I guess that's not so bad, if that's where you want to > leave it. I think one can have congruent hierarchies, although I haven't tried it yet. The idea would be to hack the PCL CPL computation instead of/in addition to UPDATE-LISP-LAYOUT. |
From: <ger...@t-...> - 2003-03-29 23:17:07
|
Christophe Rhodes <cs...@ca...> writes: > ger...@t-... (Gerd Moellmann) writes: > > > (defclass standard-object (slot-object kernel:instance) ()) It turns out that making STANDARD-OBJECT a subclass of INSTANCE is not a good idea at all when generic functions are also STANDARD-OBJECTs. The compiler then flushes checks for something being an INSTANCE when it knows it's a STANDARD-OBJECT. PCL bombed out here in (SETF SLOT-VALUE-USING-CLASS) (T STD-CLASS STANDARD-OBJECT) when called with a generic function object because of such a flushed test. But there's another hack that even works nicer: (defclass standard-object (slot-object) ()) (defclass funcallable-standard-object (standard-object kernel:funcallable-instance) () (:metaclass funcallable-standard-class)) (defclass metaobject (standard-object) ()) In other words, forget the hack from my last message. Then: (defclass class (blablah specializer kernel:instance) ()) With that, all CLOS classes are subclasses of INSTANCE, and satisfy the INSTANCE of type TYPE-SPECIFIER. Therefore (typep (find-class 'integer) 'kernel:instance) => t But (defclass foo () ()) (typep (make-instance 'foo) 'kernel:instance) => nil which means that the rest of Lisp cannot use such a TYPEP test for finding CLOS objects; STANDARD-OBJECT can be used instead. I'd find that pretty reasonable. What's your opinion? |
From: Christophe R. <cs...@ca...> - 2003-03-30 11:13:31
|
ger...@t-... (Gerd Moellmann) writes: > (defclass class (blablah specializer kernel:instance) ()) > (defclass foo () ()) > (typep (make-instance 'foo) 'kernel:instance) > => nil What does (funcall (compile nil '(lambda (x) (typep x 'kernel:instance))) (make-instance 'foo)) return in this regime? I'm guessing T :-/ > which means that the rest of Lisp cannot use such a TYPEP test for > finding CLOS objects; STANDARD-OBJECT can be used instead. > > I'd find that pretty reasonable. What's your opinion? The conclusion seems to be that there's a fairly strong impedance mismatch between the type system and the class system, right? It looks like no matter what we do, within reason, something's going to be not quite right. I can probably live with a compiler/full-call mismatch about INSTANCEness, though I would worry intensely that it would come back to bite; it does seem to be the least hideously painful option, though. Ugh, this is nasty. 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) |
From: <ger...@t-...> - 2003-03-30 11:38:53
|
Christophe Rhodes <cs...@ca...> writes: > What does > (funcall (compile nil '(lambda (x) (typep x 'kernel:instance))) > (make-instance 'foo)) > return in this regime? I'm guessing T :-/ Right. > > which means that the rest of Lisp cannot use such a TYPEP test for > > finding CLOS objects; STANDARD-OBJECT can be used instead. > > > > I'd find that pretty reasonable. What's your opinion? > > The conclusion seems to be that there's a fairly strong impedance > mismatch between the type system and the class system, right? Yes, and actually I wonder if there isn't sort of a type/representation confusion in the compiler. Or maybe not a confusion, just an assumption, and I surmise the assumption is in the instance type check transformation. > It looks like no matter what we do, within reason, something's going > to be not quite right. > > I can probably live with a compiler/full-call mismatch about > INSTANCEness, though I would worry intensely that it would come back > to bite; it does seem to be the least hideously painful option, > though. > > Ugh, this is nasty. As usual :). On a different note, just so that it gets recorded for future maintainers, what would be really nice for PCL is if the layout of instances and funcallable instances were so that their PCL-slots slot are at the same offset. That would make it possible to remove some more hair in PCL. Arranging for that doesn't seem to be too difficult, although there could be some bootstrap issues in CMUCL, or maybe not, don't know. |