src/: Stuff vtable structures into a union.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 30 Aug 2015 09:58:38 +0000 (10:58 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 9 Sep 2015 09:28:45 +0000 (10:28 +0100)
For the same reason that ichains are collected into a union: to force
the compiler's hand into getting the various members to overlap in the
common prefixes.

This doesn't affect day-to-day use, but it does change the types of the
things which are actually exported.

src/builtin.lisp
src/class-output.lisp
src/class-utilities.lisp

index 8b4407b..696bcf6 100644 (file)
@@ -95,7 +95,7 @@ static void *~A__imprint(void *p)
 {
   struct ~A *sod__obj = p;
 
-  ~:{sod__obj->~A.~A._vt = &~A;~:^~%  ~}
+  ~:{sod__obj->~A.~A._vt = &~A.~A;~:^~%  ~}
   return (p);
 }~2%"
            class
@@ -105,7 +105,8 @@ static void *~A__imprint(void *p)
                             (tail (ichain-tail ichain)))
                        (list (sod-class-nickname head)
                              (sod-class-nickname tail)
-                             (vtable-name class head))))
+                             (vtable-name class head)
+                             (sod-class-nickname tail))))
                    (ilayout-ichains ilayout)))))
 
 (define-class-slot "init" (class stream)
index 2ab6363..eb5bc26 100644 (file)
                         struct ~A {~%"
                 (vtable-struct-tag chain-tail chain-head)))
        ((class :vtable chain-head :end)
-        (format stream "};~2%"))))
+        (format stream "};~2%")
+        (format stream "/* Union of equivalent superclass vtables. */~@
+                        union ~A {~@
+                        ~:{  struct ~A ~A;~%~}~
+                        };~2%"
+                (vtable-union-tag chain-tail chain-head)
+
+                ;; As for the ichain union, make sure the most specific
+                ;; class is first.
+                (mapcar (lambda (super)
+                          (list (vtable-struct-tag super chain-head)
+                                (sod-class-nickname super)))
+                        (sod-class-chain chain-tail))))))
     (sequence-output (stream sequencer)
       ((class :vtable-externs)
-       (format stream "~@<extern const struct ~A ~2I~_~A__vtable_~A;~:>~%"
-              (vtable-struct-tag chain-tail chain-head)
+       (format stream "~@<extern const union ~A ~2I~_~A__vtable_~A;~:>~%"
+              (vtable-union-tag chain-tail chain-head)
               class (sod-class-nickname chain-head))))))
 
 (defmethod hook-output progn ((vtmsgs vtmsgs) (reason (eql :h)) sequencer)
@@ -470,12 +482,12 @@ const struct ~A ~A__classobj = {~%"
                   (class :vtables :end))
       ((class :vtable chain-head :start)
        (format stream "/* Vtable for ~A chain. */~@
-                      const struct ~A ~A = {~%"
+                      const union ~A ~A = { {~%"
               chain-head
-              (vtable-struct-tag chain-tail chain-head)
+              (vtable-union-tag chain-tail chain-head)
               (vtable-name class chain-head)))
       ((class :vtable chain-head :end)
-       (format stream "};~2%")))))
+       (format stream "} };~2%")))))
 
 (defmethod hook-output progn ((cptr class-pointer)
                              (reason (eql :c))
@@ -592,8 +604,10 @@ const struct ~A ~A__classobj = {~%"
                   (*instance-class* :object chain-head :vtable)
                   (*instance-class* :object chain-head :ichain :end))
       ((*instance-class* :object chain-head :vtable)
-       (format stream "      &~A__vtable_~A,~%"
-              class (sod-class-nickname chain-head))))))
+       (format stream "      /* ~17@A = */ &~A.~A,~%"
+              "_vt"
+              (vtable-name class chain-head)
+              (sod-class-nickname chain-tail))))))
 
 (defgeneric find-class-initializer (slot class)
   (:method ((slot effective-slot) (class sod-class))
index f00bc64..0aec35a 100644 (file)
 (defun vtmsgs-struct-tag (class super)
   (format nil "~A__vtmsgs_~A" class (sod-class-nickname super)))
 
+(export 'vtable-union-tag)
+(defun vtable-union-tag (class chain-head)
+  (format nil "~A__vtu_~A" class (sod-class-nickname chain-head)))
+
 (export 'vtable-struct-tag)
 (defun vtable-struct-tag (class chain-head)
   (format nil "~A__vt_~A" class (sod-class-nickname chain-head)))