call.lisp
来自「开源跨平台Lisp编译器」· LISP 代码 · 共 1,240 行 · 第 1/4 页
LISP
1,240 行
,@(unless variable '(nargs)) ,@(when (eq return :fixed) '(nvals)) step-instrumenting) (:ignore ,@(unless (or variable (eq return :tail)) '(arg-locs)) ,@(unless variable '(args))) (:temporary (:sc descriptor-reg :offset ocfp-offset :from (:argument 1) ,@(unless (eq return :fixed) '(:to :eval))) old-fp-pass) (:temporary (:sc descriptor-reg :offset lra-offset :from (:argument ,(if (eq return :tail) 2 1)) :to :eval) return-pc-pass) ,(if named `(:temporary (:sc descriptor-reg :offset cname-offset :from (:argument ,(if (eq return :tail) 0 1)) :to :eval) name-pass) `(:temporary (:sc descriptor-reg :offset lexenv-offset :from (:argument ,(if (eq return :tail) 0 1)) :to :eval) lexenv)) (:temporary (:scs (descriptor-reg) :from (:argument 0) :to :eval) function) (:temporary (:sc any-reg :offset nargs-offset :to :eval) nargs-pass) ,@(when variable (mapcar #'(lambda (name offset) `(:temporary (:sc descriptor-reg :offset ,offset :to :eval) ,name)) register-arg-names *register-arg-offsets*)) ,@(when (eq return :fixed) '((:temporary (:scs (descriptor-reg) :from :eval) move-temp))) (:temporary (:scs (descriptor-reg) :to :eval) stepping) ,@(unless (eq return :tail) '((:temporary (:scs (non-descriptor-reg)) temp) (:temporary (:sc control-stack :offset nfp-save-offset) nfp-save))) (:generator ,(+ (if named 5 0) (if variable 19 1) (if (eq return :tail) 0 10) 15 (if (eq return :unknown) 25 0)) (trace-table-entry trace-table-call-site) (let* ((cur-nfp (current-nfp-tn vop)) ,@(unless (eq return :tail) '((lra-label (gen-label)))) (step-done-label (gen-label)) (filler (remove nil (list :load-nargs ,@(if (eq return :tail) '((unless (location= old-fp old-fp-pass) :load-old-fp) (unless (location= return-pc return-pc-pass) :load-return-pc) (when cur-nfp :frob-nfp)) '(:comp-lra (when cur-nfp :frob-nfp) :save-fp :load-fp)))))) (flet ((do-next-filler () (let* ((next (pop filler)) (what (if (consp next) (car next) next))) (ecase what (:load-nargs ,@(if variable `((inst sub nargs-pass csp-tn new-fp) ,@(let ((index -1)) (mapcar #'(lambda (name) `(loadw ,name new-fp ,(incf index))) register-arg-names))) '((inst li nargs-pass (fixnumize nargs))))) ,@(if (eq return :tail) '((:load-old-fp (sc-case old-fp (any-reg (inst move old-fp-pass old-fp)) (control-stack (loadw old-fp-pass cfp-tn (tn-offset old-fp))))) (:load-return-pc (sc-case return-pc (descriptor-reg (inst move return-pc-pass return-pc)) (control-stack (loadw return-pc-pass cfp-tn (tn-offset return-pc))))) (:frob-nfp (inst add nsp-tn cur-nfp (- (bytes-needed-for-non-descriptor-stack-frame) number-stack-displacement)))) `((:comp-lra (inst compute-lra-from-code return-pc-pass code-tn lra-label temp)) (:frob-nfp (store-stack-tn nfp-save cur-nfp)) (:save-fp (inst move old-fp-pass cfp-tn)) (:load-fp ,(if variable '(move cfp-tn new-fp) '(if (> nargs register-arg-count) (move cfp-tn new-fp) (move cfp-tn csp-tn)))))) ((nil))))) (insert-step-instrumenting (callable-tn) ;; Conditionally insert a conditional trap: (when step-instrumenting ;; Get the symbol-value of SB!IMPL::*STEPPING* (load-symbol-value stepping sb!impl::*stepping*) (inst cmp stepping null-tn) ;; If it's not null, trap. (inst b :eq step-done-label) (inst nop) ;; FIXME: this doesn't look right. (note-this-location vop :step-before-vop) ;; Construct a trap code with the low bits from ;; SINGLE-STEP-AROUND-TRAP and the high bits from ;; the register number of CALLABLE-TN. (inst unimp (logior single-step-around-trap (ash (reg-tn-encoding callable-tn) 5))) (emit-label step-done-label)))) ,@(if named `((sc-case name (descriptor-reg (move name-pass name)) (control-stack (loadw name-pass cfp-tn (tn-offset name)) (do-next-filler)) (constant (loadw name-pass code-tn (tn-offset name) other-pointer-lowtag) (do-next-filler))) (insert-step-instrumenting name-pass) (loadw function name-pass fdefn-raw-addr-slot other-pointer-lowtag) (do-next-filler)) `((sc-case arg-fun (descriptor-reg (move lexenv arg-fun)) (control-stack (loadw lexenv cfp-tn (tn-offset arg-fun)) (do-next-filler)) (constant (loadw lexenv code-tn (tn-offset arg-fun) other-pointer-lowtag) (do-next-filler))) (loadw function lexenv closure-fun-slot fun-pointer-lowtag) (do-next-filler) (insert-step-instrumenting function))) (loop (if filler (do-next-filler) (return))) (note-this-location vop :call-site) (inst j function (- (ash simple-fun-code-offset word-shift) fun-pointer-lowtag)) (inst move code-tn function)) ,@(ecase return (:fixed '((emit-return-pc lra-label) (default-unknown-values vop values nvals move-temp temp lra-label) (when cur-nfp (load-stack-tn cur-nfp nfp-save)))) (:unknown '((emit-return-pc lra-label) (note-this-location vop :unknown-return) (receive-unknown-values values-start nvals start count lra-label temp) (when cur-nfp (load-stack-tn cur-nfp nfp-save)))) (:tail))) (trace-table-entry trace-table-normal))))(define-full-call call nil :fixed nil)(define-full-call call-named t :fixed nil)(define-full-call multiple-call nil :unknown nil)(define-full-call multiple-call-named t :unknown nil)(define-full-call tail-call nil :tail nil)(define-full-call tail-call-named t :tail nil)(define-full-call call-variable nil :fixed t)(define-full-call multiple-call-variable nil :unknown t);;; Defined separately, since needs special code that BLT's the;;; arguments down.(define-vop (tail-call-variable) (:args (args-arg :scs (any-reg) :target args) (function-arg :scs (descriptor-reg) :target lexenv) (old-fp-arg :scs (any-reg) :target old-fp) (lra-arg :scs (descriptor-reg) :target lra)) (:temporary (:sc any-reg :offset nl0-offset :from (:argument 0)) args) (:temporary (:sc any-reg :offset lexenv-offset :from (:argument 1)) lexenv) (:temporary (:sc any-reg :offset ocfp-offset :from (:argument 2)) old-fp) (:temporary (:sc any-reg :offset lra-offset :from (:argument 3)) lra) (:temporary (:scs (any-reg) :from :eval) temp) (:vop-var vop) (:generator 75 ;; Move these into the passing locations if they are not already there. (move args args-arg) (move lexenv function-arg) (move old-fp old-fp-arg) (move lra lra-arg) ;; Clear the number stack if anything is there. (let ((cur-nfp (current-nfp-tn vop))) (when cur-nfp (inst add nsp-tn cur-nfp (- (bytes-needed-for-non-descriptor-stack-frame) number-stack-displacement)))) ;; And jump to the assembly-routine that does the bliting. (inst ji temp (make-fixup 'tail-call-variable :assembly-routine)) (inst nop)));;;; Unknown values return:;;; Return a single value using the unknown-values convention.(define-vop (return-single) (:args (old-fp :scs (any-reg)) (return-pc :scs (descriptor-reg)) (value)) (:ignore value) (:vop-var vop) (:generator 6 (trace-table-entry trace-table-fun-epilogue) ;; Clear the number stack. (let ((cur-nfp (current-nfp-tn vop))) (when cur-nfp (inst add nsp-tn cur-nfp (- (bytes-needed-for-non-descriptor-stack-frame) number-stack-displacement)))) ;; Clear the control stack, and restore the frame pointer. (move csp-tn cfp-tn) (move cfp-tn old-fp) ;; Out of here. (lisp-return return-pc :offset 2) (trace-table-entry trace-table-normal)));;; Do unknown-values return of a fixed number of values. The Values are;;; required to be set up in the standard passing locations. Nvals is the;;; number of values returned.;;;;;; If returning a single value, then deallocate the current frame, restore;;; FP and jump to the single-value entry at Return-PC + 8.;;;;;; If returning other than one value, then load the number of values returned,;;; NIL out unsupplied values registers, restore FP and return at Return-PC.;;; When there are stack values, we must initialize the argument pointer to;;; point to the beginning of the values block (which is the beginning of the;;; current frame.)(define-vop (return) (:args (old-fp :scs (any-reg)) (return-pc :scs (descriptor-reg) :to (:eval 1)) (values :more t)) (:ignore values) (:info nvals) (:temporary (:sc descriptor-reg :offset a0-offset :from (:eval 0)) a0) (:temporary (:sc descriptor-reg :offset a1-offset :from (:eval 0)) a1) (:temporary (:sc descriptor-reg :offset a2-offset :from (:eval 0)) a2) (:temporary (:sc descriptor-reg :offset a3-offset :from (:eval 0)) a3) (:temporary (:sc descriptor-reg :offset a4-offset :from (:eval 0)) a4) (:temporary (:sc descriptor-reg :offset a5-offset :from (:eval 0)) a5) (:temporary (:sc any-reg :offset nargs-offset) nargs) (:temporary (:sc any-reg :offset ocfp-offset) val-ptr) (:vop-var vop) (:generator 6 (trace-table-entry trace-table-fun-epilogue) ;; Clear the number stack. (let ((cur-nfp (current-nfp-tn vop))) (when cur-nfp (inst add nsp-tn cur-nfp (- (bytes-needed-for-non-descriptor-stack-frame) number-stack-displacement))))
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?