~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to pcl/extensions/inline.lisp

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
 
2
 
 
3
(in-package :pcl)
 
4
 
 
5
;; This file contains some of the things that will have to change to support
 
6
;; inlining of methods.
 
7
 
 
8
(defun make-method-lambda-internal (method-lambda &optional env)
 
9
  (unless (and (consp method-lambda) (eq (car method-lambda) 'lambda))
 
10
    (error "The method-lambda argument to make-method-lambda, ~S,~
 
11
            is not a lambda form" method-lambda))
 
12
  (multiple-value-bind (documentation declarations real-body)
 
13
      (extract-declarations (cddr method-lambda) env)
 
14
    (let* ((name-decl (get-declaration 'method-name declarations))
 
15
           (sll-decl (get-declaration 'method-lambda-list declarations))
 
16
           (method-name (when (consp name-decl) (car name-decl)))
 
17
           (generic-function-name (when method-name (car method-name)))
 
18
           (specialized-lambda-list (or sll-decl (cadr method-lambda))))
 
19
      (multiple-value-bind (parameters lambda-list specializers)
 
20
          (parse-specialized-lambda-list specialized-lambda-list)
 
21
        (let* ((required-parameters
 
22
                (mapcar #'(lambda (r s) (declare (ignore s)) r)
 
23
                        parameters
 
24
                        specializers))
 
25
               (slots (mapcar #'list required-parameters))
 
26
               (calls (list nil))
 
27
               (parameters-to-reference
 
28
                (make-parameter-references specialized-lambda-list
 
29
                                           required-parameters
 
30
                                           declarations
 
31
                                           method-name
 
32
                                           specializers))
 
33
               (class-declarations
 
34
                `(declare
 
35
                  ,@(remove nil
 
36
                            (mapcar #'(lambda (a s) (and (symbolp s)
 
37
                                                         (neq s 't)
 
38
                                                         `(class ,a ,s)))
 
39
                                    parameters
 
40
                                    specializers))))
 
41
               (method-lambda
 
42
                  ;; Remove the documentation string and insert the
 
43
                  ;; appropriate class declarations.  The documentation
 
44
                  ;; string is removed to make it easy for us to insert
 
45
                  ;; new declarations later, they will just go after the
 
46
                  ;; cadr of the method lambda.  The class declarations
 
47
                  ;; are inserted to communicate the class of the method's
 
48
                  ;; arguments to the code walk.
 
49
                  `(lambda ,lambda-list
 
50
                     ,class-declarations
 
51
                     ,@declarations
 
52
                     (progn ,@parameters-to-reference)
 
53
                     (block ,(if (listp generic-function-name)
 
54
                                 (cadr generic-function-name)
 
55
                                 generic-function-name)
 
56
                       ,@real-body)))
 
57
               (constant-value-p (and (null (cdr real-body))
 
58
                                      (constantp (car real-body))))
 
59
               (constant-value (and constant-value-p
 
60
                                    (eval (car real-body))))
 
61
               (plist (if (and constant-value-p
 
62
                               (or (typep constant-value '(or number character))
 
63
                                   (and (symbolp constant-value)
 
64
                                        (symbol-package constant-value))))
 
65
                          (list :constant-value constant-value)
 
66
                          ()))
 
67
               (applyp (dolist (p lambda-list nil)
 
68
                         (cond ((memq p '(&optional &rest &key))
 
69
                                (return t))
 
70
                               ((eq p '&aux)
 
71
                                (return nil))))))
 
72
            (multiple-value-bind (walked-lambda call-next-method-p closurep
 
73
                                                next-method-p-p)
 
74
                (walk-method-lambda method-lambda required-parameters env 
 
75
                                    slots calls)
 
76
              (multiple-value-bind (ignore walked-declarations walked-lambda-body)
 
77
                  (extract-declarations (cddr walked-lambda))
 
78
                (declare (ignore ignore))
 
79
                (when (or next-method-p-p call-next-method-p)
 
80
                  (setq plist (list* :needs-next-methods-p 't plist)))
 
81
                (when (some #'cdr slots)
 
82
                  (multiple-value-bind (slot-name-lists call-list)
 
83
                      (slot-name-lists-from-slots slots calls)
 
84
                    (let ((pv-table-symbol (make-symbol "pv-table")))
 
85
                      (setq plist 
 
86
                            `(,@(when slot-name-lists 
 
87
                                  `(:slot-name-lists ,slot-name-lists))
 
88
                              ,@(when call-list
 
89
                                  `(:call-list ,call-list))
 
90
                              :pv-table-symbol ,pv-table-symbol
 
91
                              ,@plist))
 
92
                      (setq walked-lambda-body
 
93
                            `((pv-binding (,required-parameters ,slot-name-lists
 
94
                                           ,pv-table-symbol)
 
95
                               ,@walked-lambda-body))))))
 
96
                (when (and (memq '&key lambda-list)
 
97
                           (not (memq '&allow-other-keys lambda-list)))
 
98
                  (let ((aux (memq '&aux lambda-list)))
 
99
                    (setq lambda-list (nconc (ldiff lambda-list aux)
 
100
                                             (list '&allow-other-keys)
 
101
                                             aux))))
 
102
                (values `(lambda (.method-args. .next-methods.)
 
103
                           (simple-lexical-method-functions
 
104
                               (,lambda-list .method-args. .next-methods.
 
105
                                :call-next-method-p ,call-next-method-p 
 
106
                                :next-method-p-p ,next-method-p-p
 
107
                                :closurep ,closurep
 
108
                                :applyp ,applyp)
 
109
                             ,@walked-declarations
 
110
                             ,@walked-lambda-body))
 
111
                        `(,@(when plist 
 
112
                              `(:plist ,plist))
 
113
                          ,@(when documentation 
 
114
                              `(:documentation ,documentation)))))))))))
 
115
 
 
116
(define-inline-function slot-value (instance slot-name) (form closure-p env)
 
117
  :predicate (and (not closure-p) (constantp slot-name))
 
118
  :inline-arguments (required-parameters slots)
 
119
  :inline (optimize-slot-value     
 
120
           slots
 
121
           (can-optimize-access form required-parameters env)
 
122
           form))
 
123
 
 
124
;collect information about:
 
125
; uses of the required-parameters
 
126
; uses of call-next-method and next-method-p:
 
127
;   called-p
 
128
;   apply-p
 
129
;   arglist info
 
130
;optimize calls to slot-value, set-slot-value, slot-boundp
 
131
;optimize calls to find-class
 
132
;optimize generic-function calls
 
133
(defun make-walk-function (required-parameters info slots calls)
 
134
  #'(lambda (form context env)
 
135
      (cond ((not (eq context ':eval)) form)
 
136
            ((not (listp form)) form)
 
137
            ((eq (car form) 'call-next-method)
 
138
             (setq call-next-method-p 't)
 
139
             form)
 
140
            ((eq (car form) 'next-method-p)
 
141
             (setq next-method-p-p 't)
 
142
             form)
 
143
            ((and (eq (car form) 'function)
 
144
                  (cond ((eq (cadr form) 'call-next-method)
 
145
                         (setq call-next-method-p 't)
 
146
                         (setq closurep t)
 
147
                         form)
 
148
                        ((eq (cadr form) 'next-method-p)
 
149
                         (setq next-method-p-p 't)
 
150
                         (setq closurep t)
 
151
                         form)
 
152
                        (t nil))))
 
153
            ((and (or (eq (car form) 'slot-value)
 
154
                      (eq (car form) 'set-slot-value)
 
155
                      (eq (car form) 'slot-boundp))
 
156
                  (constantp (caddr form)))
 
157
             (let ((parameter
 
158
                    (can-optimize-access form
 
159
                                         required-parameters env)))
 
160
               (ecase (car form)
 
161
                 (slot-value
 
162
                  (optimize-slot-value     slots parameter form))
 
163
                 (set-slot-value
 
164
                  (optimize-set-slot-value slots parameter form))
 
165
                 (slot-boundp
 
166
                  (optimize-slot-boundp    slots parameter form)))))
 
167
            ((and (or (symbolp (car form))
 
168
                      (and (consp (car form))
 
169
                           (eq (caar form) 'setf)))
 
170
                  (gboundp (car form))
 
171
                  (if (eq *boot-state* 'complete)
 
172
                      (standard-generic-function-p (gdefinition (car form)))
 
173
                      (funcallable-instance-p (gdefinition (car form)))))
 
174
             (optimize-generic-function-call 
 
175
              form required-parameters env slots calls))
 
176
            (t form))))
 
177
 
 
178
(defun walk-method-lambda (method-lambda required-parameters env slots calls)
 
179
  (let* ((call-next-method-p nil)   ;flag indicating that call-next-method
 
180
                                    ;should be in the method definition
 
181
         (closurep nil)             ;flag indicating that #'call-next-method
 
182
                                    ;was seen in the body of a method
 
183
         (next-method-p-p nil)      ;flag indicating that next-method-p
 
184
                                    ;should be in the method definition
 
185
         (walk-functions `((call-next-method-p
 
186
                            ,#'(lambda (form closure-p env)
 
187
                                 (setq call-next-method-p 't)
 
188
                                 (when closure-p
 
189
                                   (setq closurep t))
 
190
                                 form))
 
191
                           (next-method-p
 
192
                            ,#'(lambda (form closure-p env)
 
193
                                 (setq next-method-p-p 't)
 
194
                                 (when closure-p
 
195
                                   (setq closurep t))
 
196
                                 form))
 
197
                           ((slot-value set-slot-value slot-boundp)
 
198
                            ,#'(lambda (form closure-p env)
 
199
                                 (if (and (not closure-p)
 
200
                                          (constantp (caddr form)))
 
201
                                     
 
202
    (let ((walked-lambda (walk-form method-lambda env 
 
203
                                    (make-walk-function 
 
204
                                     `((call-next-method-p
 
205
                                        ,#'(lambda (form closure-p env)
 
206
                                             (setq call-next-method-p 't)
 
207
                                             (when closure-p
 
208
                                               (setq closurep t))
 
209
                                             form))
 
210
                                       (next-method-p
 
211
                                        ,#'(lambda (form closure-p env)
 
212
                                             (setq next-method-p-p 't)
 
213
                                             (when closure-p
 
214
                                               (setq closurep t))
 
215
                                             form))
 
216
                                       ((slot-value set-slot-value slot-boundp)
 
217
                                        ,#'(lambda (form closure-p env)
 
218
                                             (
 
219
      (values walked-lambda
 
220
              call-next-method-p closurep next-method-p-p)))))
 
221
 
 
222
(defun initialize-method-function (initargs &optional return-function-p method)
 
223
  (let* ((mf (getf initargs ':function))
 
224
         (method-spec (getf initargs ':method-spec))
 
225
         (plist (getf initargs ':plist))
 
226
         (pv-table-symbol (getf plist ':pv-table-symbol))
 
227
         (pv-table nil)
 
228
         (mff (getf initargs ':fast-function)))
 
229
    (flet ((set-mf-property (p v)
 
230
             (when mf
 
231
               (setf (method-function-get mf p) v))
 
232
             (when mff
 
233
               (setf (method-function-get mff p) v))))
 
234
      (when method-spec
 
235
        (when mf
 
236
          (setq mf (set-function-name mf method-spec)))
 
237
        (when mff
 
238
          (let ((name `(,(or (get (car method-spec) 'fast-sym)
 
239
                             (setf (get (car method-spec) 'fast-sym)
 
240
                                   (intern (format nil "FAST-~A"
 
241
                                                   (car method-spec))
 
242
                                           *the-pcl-package*)))
 
243
                         ,@(cdr method-spec))))
 
244
            (set-function-name mff name)
 
245
            (unless mf
 
246
              (set-mf-property :name name)))))
 
247
      (when plist
 
248
        (let ((snl (getf plist :slot-name-lists))
 
249
              (cl (getf plist :call-list)))
 
250
          (when (or snl cl)
 
251
            (setq pv-table (intern-pv-table :slot-name-lists snl
 
252
                                            :call-list cl))
 
253
            (when pv-table (set pv-table-symbol pv-table))
 
254
            (set-mf-property :pv-table pv-table)))    
 
255
        (loop (when (null plist) (return nil))
 
256
              (set-mf-property (pop plist) (pop plist)))      
 
257
        (when method
 
258
          (set-mf-property :method method))    
 
259
        (when return-function-p
 
260
          (or mf (method-function-from-fast-function mff)))))))
 
261
 
 
262
 
 
263