diff options
author | Andy Wingo <wingo@pobox.com> | 2015-01-23 14:55:35 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2015-01-23 16:16:04 +0100 |
commit | 4bde3f04ea2c573a871b5f377b5f41d970dc8ebe (patch) | |
tree | 8b77684c10c7fb60b52e339a112e5fa2cd42269b /module/oop | |
parent | 193e2c52dc18ea79ec37cef744ea8c6ef97c2cb3 (diff) |
Simplify and optimize slot access
* module/oop/goops.scm (fold-slot-slots): Add `slot-ref/raw' slot, which
is what the slot-ref slot was. Now the slot-ref slot checks that the
slot is bound, if needed.
(slot-definition-slot-ref/raw): Define.
(make-slot): Adapt. Also, effective slot definition slots have no
initargs.
(define-standard-accessor-method, bound-check-get, standard-get)
(standard-set): Move definitions up.
(allocate-slots): Adapt. If the slot has an init thunk, we don't need
to check that it's bound.
(slot-ref, slot-set!, slot-bound?): Simplify.
(class-slot-ref): Use the raw getter so that we can call
`slot-unbound' with just the class.
(compute-getter-method, compute-setter-method): Simplify to just use
the slot-ref / slot-set! functions from the slot.
(%initialize-object): Simplify.
Diffstat (limited to 'module/oop')
-rw-r--r-- | module/oop/goops.scm | 153 |
1 files changed, 68 insertions, 85 deletions
diff --git a/module/oop/goops.scm b/module/oop/goops.scm index e7df3681b..1c4fd7de2 100644 --- a/module/oop/goops.scm +++ b/module/oop/goops.scm @@ -208,6 +208,7 @@ (accessor #:init-keyword #:accessor #:init-value #f) ;; These last don't have #:init-keyword because they are meant to be ;; set by `allocate-slots', not in compute-effective-slot-definition. + (slot-ref/raw #:init-value #f) (slot-ref #:init-value #f) (slot-set! #:init-value #f) (index #:init-value #f) @@ -476,11 +477,14 @@ followed by its associated value. If @var{l} does not hold a value for (define-slot-accessor slot-definition-accessor "Return the accessor of the slot @var{obj}, or @code{#f}." %slot-definition-accessor slot-index-accessor) +(define-slot-accessor slot-definition-slot-ref/raw + "Return the raw slot-ref procedure of the slot @var{obj}." + %slot-definition-slot-ref/raw slot-index-slot-ref/raw) (define-slot-accessor slot-definition-slot-ref - "Return the slot-ref procedure of the slot @var{obj}, or @code{#f}." + "Return the slot-ref procedure of the slot @var{obj}." %slot-definition-slot-ref slot-index-slot-ref) (define-slot-accessor slot-definition-slot-set! - "Return the slot-set! procedure of the slot @var{obj}, or @code{#f}." + "Return the slot-set! procedure of the slot @var{obj}." %slot-definition-slot-set! slot-index-slot-set!) (define-slot-accessor slot-definition-index "Return the allocated struct offset of the slot @var{obj}, or @code{#f}." @@ -513,10 +517,11 @@ followed by its associated value. If @var{l} does not hold a value for (init-slot slot-index-getter #:getter #f) (init-slot slot-index-setter #:setter #f) (init-slot slot-index-accessor #:accessor #f) - (init-slot slot-index-slot-ref #:slot-ref #f) - (init-slot slot-index-slot-set! #:slot-set! #f) - (init-slot slot-index-index #:index #f) - (init-slot slot-index-size #:size #f) + (struct-set! slot slot-index-slot-ref/raw #f) + (struct-set! slot slot-index-slot-ref #f) + (struct-set! slot slot-index-slot-set! #f) + (struct-set! slot slot-index-index #f) + (struct-set! slot slot-index-size #f) slot)) ;; Boot definition. @@ -678,6 +683,35 @@ followed by its associated value. If @var{l} does not hold a value for (struct-set! class class-index-nfields (1+ index)) index)) +;;; Pre-generate getters and setters for the first 20 slots. +(define-syntax define-standard-accessor-method + (lambda (stx) + (define num-standard-pre-cache 20) + (syntax-case stx () + ((_ ((proc n) arg ...) body) + #`(define proc + (let ((cache (vector #,@(map (lambda (n*) + #`(lambda (arg ...) + (let ((n #,n*)) + body))) + (iota num-standard-pre-cache))))) + (lambda (n) + (if (< n #,num-standard-pre-cache) + (vector-ref cache n) + (lambda (arg ...) body))))))))) + +(define-standard-accessor-method ((bound-check-get n) o) + (let ((x (struct-ref o n))) + (if (unbound? x) + (slot-unbound o) + x))) + +(define-standard-accessor-method ((standard-get n) o) + (struct-ref o n)) + +(define-standard-accessor-method ((standard-set n) o v) + (struct-set! o n v)) + (define (allocate-slots class slots) "Transform the computed list of direct slot definitions @var{slots} into a corresponding list of effective slot definitions, allocating @@ -687,6 +721,7 @@ slots as we go." ;; allocates a field to the object. Pretty strange, but we preserve ;; the behavior for backward compatibility. (let* ((slot (compute-effective-slot-definition class slot)) + (name (%slot-definition-name slot)) (index (struct-ref class class-index-nfields)) (g-n-s (compute-get-n-set class slot)) (size (- (struct-ref class class-index-nfields) index))) @@ -696,14 +731,25 @@ slots as we go." ((? integer?) (unless (= size 1) (error "unexpected return from compute-get-n-set")) - (values #f #f)) + (values (standard-get g-n-s) + (if (slot-definition-init-thunk slot) + (standard-get g-n-s) + (bound-check-get g-n-s)) + (standard-set g-n-s))) (((? procedure? get) (? procedure? set)) - (values get set)))) - (lambda (get set) - (struct-set! slot slot-index-index index) - (struct-set! slot slot-index-size size) + (values get + (lambda (o) + (let ((value (get o))) + (if (unbound? value) + (slot-unbound class o name) + value))) + set)))) + (lambda (get/raw get set) + (struct-set! slot slot-index-slot-ref/raw get/raw) (struct-set! slot slot-index-slot-ref get) - (struct-set! slot slot-index-slot-set! set))) + (struct-set! slot slot-index-slot-set! set) + (struct-set! slot slot-index-index index) + (struct-set! slot slot-index-size size))) slot)) (struct-set! class class-index-nfields 0) (map-in-order make-effective-slot-definition slots)) @@ -1081,17 +1127,8 @@ function." (define (slot-ref obj slot-name) "Return the value from @var{obj}'s slot with the nam var{slot_name}." (let ((class (class-of obj))) - (define (slot-value slot) - (cond - ((%slot-definition-slot-ref slot) - => (lambda (slot-ref) (slot-ref obj))) - (else - (struct-ref obj (%slot-definition-index slot))))) (define (have-slot slot) - (let ((val (slot-value slot))) - (if (unbound? val) - (slot-unbound class obj slot-name) - val))) + ((%slot-definition-slot-ref slot) obj)) (define (no-slot) (unless (symbol? slot-name) (scm-error 'wrong-type-arg #f "Not a symbol: ~S" @@ -1106,11 +1143,7 @@ function." "Set the slot named @var{slot_name} of @var{obj} to @var{value}." (let ((class (class-of obj))) (define (have-slot slot) - (cond - ((%slot-definition-slot-set! slot) - => (lambda (slot-set!) (slot-set! obj value))) - (else - (struct-set! obj (%slot-definition-index slot) value)))) + ((%slot-definition-slot-set! slot) obj value)) (define (no-slot) (unless (symbol? slot-name) (scm-error 'wrong-type-arg #f "Not a symbol: ~S" @@ -1122,22 +1155,13 @@ function." (define (slot-bound? obj slot-name) "Return the value from @var{obj}'s slot with the nam var{slot_name}." (let ((class (class-of obj))) - (define (slot-value slot) - (cond - ((%slot-definition-slot-ref slot) - => (lambda (slot-ref) (slot-ref obj))) - (else - (struct-ref obj (%slot-definition-index slot))))) (define (have-slot slot) - (not (unbound? (slot-value slot)))) + (not (unbound? ((%slot-definition-slot-ref/raw slot) obj)))) (define (no-slot) (unless (symbol? slot-name) (scm-error 'wrong-type-arg #f "Not a symbol: ~S" (list slot-name) #f)) - (let ((val (slot-missing class obj slot-name))) - (if (unbound? val) - (slot-unbound class obj slot-name) - val))) + (not (unbound? (slot-missing class obj slot-name)))) (%class-slot-definition class slot-name have-slot no-slot))) (define (slot-exists? obj slot-name) @@ -2408,7 +2432,7 @@ function." (let ((slot (class-slot-definition class slot-name))) (unless (memq (%slot-definition-allocation slot) '(#:class #:each-subclass)) (slot-missing class slot-name)) - (let ((x ((%slot-definition-slot-ref slot) #f))) + (let ((x ((%slot-definition-slot-ref/raw slot) #f))) (if (unbound? x) (slot-unbound class slot-name) x)))) @@ -2611,25 +2635,17 @@ function." slots)) (define-method (compute-getter-method (class <class>) slot) - (let ((init-thunk (slot-definition-init-thunk slot)) - (slot-ref (slot-definition-slot-ref slot)) - (index (slot-definition-index slot))) + (let ((slot-ref (slot-definition-slot-ref slot))) (make <accessor-method> #:specializers (list class) - #:procedure (cond - (slot-ref (make-generic-bound-check-getter slot-ref)) - (init-thunk (standard-get index)) - (else (bound-check-get index))) + #:procedure slot-ref #:slot-definition slot))) (define-method (compute-setter-method (class <class>) slot) - (let ((slot-set! (slot-definition-slot-set! slot)) - (index (slot-definition-index slot))) + (let ((slot-set! (slot-definition-slot-set! slot))) (make <accessor-method> #:specializers (list class <top>) - #:procedure (cond - (slot-set! slot-set!) - (else (standard-set index))) + #:procedure slot-set! #:slot-definition slot))) (define (make-generic-bound-check-getter proc) @@ -2639,35 +2655,6 @@ function." (slot-unbound o) val)))) -;;; Pre-generate getters and setters for the first 20 slots. -(define-syntax define-standard-accessor-method - (lambda (stx) - (define num-standard-pre-cache 20) - (syntax-case stx () - ((_ ((proc n) arg ...) body) - #`(define proc - (let ((cache (vector #,@(map (lambda (n*) - #`(lambda (arg ...) - (let ((n #,n*)) - body))) - (iota num-standard-pre-cache))))) - (lambda (n) - (if (< n #,num-standard-pre-cache) - (vector-ref cache n) - (lambda (arg ...) body))))))))) - -(define-standard-accessor-method ((bound-check-get n) o) - (let ((x (struct-ref o n))) - (if (unbound? x) - (slot-unbound o) - x))) - -(define-standard-accessor-method ((standard-get n) o) - (struct-ref o n)) - -(define-standard-accessor-method ((standard-set n) o v) - (struct-set! o n v)) - ;;; compute-cpl ;;; @@ -2778,11 +2765,7 @@ var{initargs}." (() obj) ((slot . slots) (define (initialize-slot! value) - (cond - ((%slot-definition-slot-set! slot) - => (lambda (slot-set!) (slot-set! obj value))) - (else - (struct-set! obj (%slot-definition-index slot) value)))) + ((%slot-definition-slot-set! slot) obj value)) (let ((initarg (get-initarg (%slot-definition-init-keyword slot)))) (cond ((not (unbound? initarg)) |