1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-11 14:21:10 +02:00

Use a vtable bit to mark <slot> instances

* libguile/goops.h (SCM_VTABLE_FLAG_GOOPS_SLOT): Allocate another vtable
  flag to indicate that instances of this vtable are slots.
* libguile/goops.c (scm_init_goops_builtins): Export
  vtable-flag-goops-slot to Scheme.

* module/oop/goops.scm (<slot>, slot?, make-standard-class, initialize):
  Arrange for <slot> classes to have the vtable-flag-goops.slot.
  (build-slots-list): Ensure that <slot> slots are statically laid out.
This commit is contained in:
Andy Wingo 2015-01-18 21:01:31 +01:00
parent 568174d173
commit e437c50b88
3 changed files with 35 additions and 19 deletions

View file

@ -1053,6 +1053,8 @@ scm_init_goops_builtins (void *unused)
scm_from_int (SCM_VTABLE_FLAG_GOOPS_CLASS)); scm_from_int (SCM_VTABLE_FLAG_GOOPS_CLASS));
scm_c_define ("vtable-flag-goops-valid", scm_c_define ("vtable-flag-goops-valid",
scm_from_int (SCM_VTABLE_FLAG_GOOPS_VALID)); scm_from_int (SCM_VTABLE_FLAG_GOOPS_VALID));
scm_c_define ("vtable-flag-goops-slot",
scm_from_int (SCM_VTABLE_FLAG_GOOPS_SLOT));
} }
void void

View file

@ -42,6 +42,7 @@
*/ */
#define SCM_VTABLE_FLAG_GOOPS_CLASS SCM_VTABLE_FLAG_GOOPS_0 #define SCM_VTABLE_FLAG_GOOPS_CLASS SCM_VTABLE_FLAG_GOOPS_0
#define SCM_VTABLE_FLAG_GOOPS_VALID SCM_VTABLE_FLAG_GOOPS_1 #define SCM_VTABLE_FLAG_GOOPS_VALID SCM_VTABLE_FLAG_GOOPS_1
#define SCM_VTABLE_FLAG_GOOPS_SLOT SCM_VTABLE_FLAG_GOOPS_2
#define SCM_CLASS_OF(x) SCM_STRUCT_VTABLE (x) #define SCM_CLASS_OF(x) SCM_STRUCT_VTABLE (x)
#define SCM_CLASS_FLAGS(class) (SCM_VTABLE_FLAGS (class)) #define SCM_CLASS_FLAGS(class) (SCM_VTABLE_FLAGS (class))

View file

@ -413,6 +413,7 @@ followed by its associated value. If @var{l} does not hold a value for
(nfields (/ (string-length layout) 2)) (nfields (/ (string-length layout) 2))
(<slot> (make-struct/no-tail <class> (make-struct-layout layout)))) (<slot> (make-struct/no-tail <class> (make-struct-layout layout))))
(class-add-flags! <slot> (logior vtable-flag-goops-class (class-add-flags! <slot> (logior vtable-flag-goops-class
vtable-flag-goops-slot
vtable-flag-goops-valid)) vtable-flag-goops-valid))
(struct-set! <slot> class-index-name '<slot>) (struct-set! <slot> class-index-name '<slot>)
(struct-set! <slot> class-index-nfields nfields) (struct-set! <slot> class-index-nfields nfields)
@ -425,8 +426,9 @@ followed by its associated value. If @var{l} does not hold a value for
(struct-set! <slot> class-index-redefined #f) (struct-set! <slot> class-index-redefined #f)
<slot>))) <slot>)))
(define (slot? obj) (define-inlinable (slot? obj)
(is-a? obj <slot>)) (and (struct? obj)
(class-has-flags? (struct-vtable obj) vtable-flag-goops-slot)))
(define-syntax-rule (define-slot-accessor name docstring field) (define-syntax-rule (define-slot-accessor name docstring field)
(define (name obj) (define (name obj)
@ -632,10 +634,10 @@ followed by its associated value. If @var{l} does not hold a value for
(() #f) (() #f)
((slot . slots) ((slot . slots)
(or (eq? (slot-definition-name slot) name) (lp slots))))))) (or (eq? (slot-definition-name slot) name) (lp slots)))))))
(define (check-cpl slots class-slots ) (define (check-cpl slots static-slots)
(when (or-map (lambda (slot) (slot-memq slot slots)) class-slots) (when (or-map (lambda (slot) (slot-memq slot slots)) static-slots)
(scm-error 'misc-error #f (scm-error 'misc-error #f
"a predefined <class> inherited field cannot be redefined" "a predefined static inherited field cannot be redefined"
'() '()))) '() '())))
(define (remove-duplicate-slots slots) (define (remove-duplicate-slots slots)
(let lp ((slots (reverse slots)) (res '()) (seen '())) (let lp ((slots (reverse slots)) (res '()) (seen '()))
@ -646,26 +648,31 @@ followed by its associated value. If @var{l} does not hold a value for
(if (memq name seen) (if (memq name seen)
(lp slots res seen) (lp slots res seen)
(lp slots (cons slot res) (cons name seen)))))))) (lp slots (cons slot res) (cons name seen))))))))
;; FIXME: the thing we do for <class> ensures static slot allocation. ;; For subclases of <class> and <slot>, we need to ensure that the
;; do the same thing for <slot>. ;; <class> or <slot> slots come first.
(let* ((class-slots (and (memq <class> cpl) (let* ((static-slots (cond
(struct-ref <class> class-index-slots)))) ((memq <class> cpl)
(when class-slots (when (memq <slot> cpl) (error "invalid class"))
(check-cpl dslots class-slots)) (struct-ref <class> class-index-slots))
(let lp ((cpl (cdr cpl)) (res dslots) (class-slots '())) ((memq <slot> cpl)
(struct-ref <slot> class-index-slots))
(else #f))))
(when static-slots
(check-cpl dslots static-slots))
(let lp ((cpl (cdr cpl)) (res dslots) (static-slots '()))
(match cpl (match cpl
(() (remove-duplicate-slots (append class-slots res))) (() (remove-duplicate-slots (append static-slots res)))
((head . cpl) ((head . cpl)
(let ((new-slots (struct-ref head class-index-direct-slots))) (let ((new-slots (struct-ref head class-index-direct-slots)))
(cond (cond
((not class-slots) ((not static-slots)
(lp cpl (append new-slots res) class-slots)) (lp cpl (append new-slots res) static-slots))
((eq? head <class>) ((or (eq? head <class>) (eq? head <slot>))
;; Move class slots to the head of the list. ;; Move static slots to the head of the list.
(lp cpl res new-slots)) (lp cpl res new-slots))
(else (else
(check-cpl new-slots class-slots) (check-cpl new-slots static-slots)
(lp cpl (append new-slots res) class-slots))))))))) (lp cpl (append new-slots res) static-slots)))))))))
;; Boot definition. ;; Boot definition.
(define (compute-get-n-set class slot) (define (compute-get-n-set class slot)
@ -769,6 +776,8 @@ slots as we go."
(struct-set! z class-index-redefined #f) (struct-set! z class-index-redefined #f)
(let ((cpl (compute-cpl z))) (let ((cpl (compute-cpl z)))
(struct-set! z class-index-cpl cpl) (struct-set! z class-index-cpl cpl)
(when (memq <slot> cpl)
(class-add-flags! z vtable-flag-goops-slot))
(let* ((dslots (map make-direct-slot-definition dslots)) (let* ((dslots (map make-direct-slot-definition dslots))
(slots (allocate-slots z (build-slots-list dslots cpl)))) (slots (allocate-slots z (build-slots-list dslots cpl))))
(struct-set! z class-index-direct-slots dslots) (struct-set! z class-index-direct-slots dslots)
@ -2769,6 +2778,10 @@ var{initargs}."
(struct-set! class class-index-slots (struct-set! class class-index-slots
(allocate-slots class (compute-slots class))) (allocate-slots class (compute-slots class)))
;; This is a hack.
(when (memq <slot> (struct-ref class class-index-cpl))
(class-add-flags! class vtable-flag-goops-slot))
;; Build getters - setters - accessors ;; Build getters - setters - accessors
(compute-slot-accessors class (struct-ref class class-index-slots)) (compute-slot-accessors class (struct-ref class class-index-slots))