call.lisp

来自「开源跨平台Lisp编译器」· LISP 代码 · 共 1,244 行 · 第 1/4 页

LISP
1,244
字号
  (: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)  #!-gengc (:temporary (:scs (interior-reg)) lip)  #!+gengc (:temporary (:sc any-reg :offset ra-offset :from (:eval 1)) ra)  (:vop-var vop)  (:generator 6    ;; Clear the number stack.    (trace-table-entry trace-table-fun-epilogue)    (let ((cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (inst addq cur-nfp (bytes-needed-for-non-descriptor-stack-frame)              nsp-tn)))    ;; Establish the values pointer and values count.    (move cfp-tn val-ptr)    (inst li (fixnumize nvals) nargs)    ;; restore the frame pointer and clear as much of the control    ;; stack as possible.    (move ocfp cfp-tn)    ;; ADDQ only accepts immediates of type (UNSIGNED-BYTE 8).  Here,    ;; instead of adding (* NVALS N-WORD-BYTES), we use NARGS that    ;; we've carefully set up, but protect ourselves by averring that    ;; FIXNUMIZEation and multiplication by N-WORD-BYTES is the same.    (aver (= (* nvals n-word-bytes) (fixnumize nvals)))    (inst addq val-ptr nargs csp-tn)    ;; pre-default any argument register that need it.    (when (< nvals register-arg-count)      (dolist (reg (subseq (list a0 a1 a2 a3 a4 a5) nvals))        (move null-tn reg)))    ;; And away we go.    (lisp-return return-pc lip)    (trace-table-entry trace-table-normal)));;; Do unknown-values return of an arbitrary number of values (passed;;; on the stack.) We check for the common case of a single return;;; value, and do that inline using the normal single value return;;; convention. Otherwise, we branch off to code that calls an;;; assembly-routine.(define-vop (return-multiple)  (:args (ocfp-arg :scs (any-reg) :target ocfp)         #!-gengc (lra-arg :scs (descriptor-reg) :target lra)         #!+gengc (return-pc :scs (any-reg) :target ra)         (vals-arg :scs (any-reg) :target vals)         (nvals-arg :scs (any-reg) :target nvals))  (:temporary (:sc any-reg :offset nl1-offset :from (:argument 0)) ocfp)  #!-gengc  (:temporary (:sc descriptor-reg :offset lra-offset :from (:argument 1)) lra)  #!+gengc  (:temporary (:sc any-reg :offset ra-offset :from (:argument 1)) ra)  (:temporary (:sc any-reg :offset nl0-offset :from (:argument 2)) vals)  (:temporary (:sc any-reg :offset nargs-offset :from (:argument 3)) nvals)  (:temporary (:sc descriptor-reg :offset a0-offset) a0)  (:temporary (:scs (non-descriptor-reg)) temp)  #!-gengc (:temporary (:scs (interior-reg)) lip)  #!+gengc (:temporary (:scs (any-reg) :from (:argument 0)) temp)  (:vop-var vop)  (:generator 13    (trace-table-entry trace-table-fun-epilogue)    (let ((not-single (gen-label)))      ;; Clear the number stack.      (let ((cur-nfp (current-nfp-tn vop)))        (when cur-nfp          (inst addq cur-nfp (bytes-needed-for-non-descriptor-stack-frame)                nsp-tn)))      ;; Check for the single case.      (inst li (fixnumize 1) a0)      (inst cmpeq nvals-arg a0 temp)      (inst ldl a0 0 vals-arg)      (inst beq temp not-single)      ;; Return with one value.      (move cfp-tn csp-tn)      (move ocfp-arg cfp-tn)      (lisp-return lra-arg lip :offset 2)      ;; Nope, not the single case.      (emit-label not-single)      (move ocfp-arg ocfp)      (move lra-arg lra)      (move vals-arg vals)      (move nvals-arg nvals)      (inst li (make-fixup 'return-multiple :assembly-routine) temp)      (inst jmp zero-tn temp))    (trace-table-entry trace-table-normal)));;;; XEP hackery;;; We don't need to do anything special for regular functions.(define-vop (setup-environment)  (:info label)  (:ignore label)  (:generator 0    ;; Don't bother doing anything.    ));;; Get the lexical environment from its passing location.(define-vop (setup-closure-environment)  (:temporary (:sc descriptor-reg :offset lexenv-offset :target closure               :to (:result 0))              lexenv)  (:results (closure :scs (descriptor-reg)))  (:info label)  (:ignore label)  (:generator 6    ;; Get result.    (move lexenv closure)));;; Copy a &MORE arg from the argument area to the end of the current;;; frame. FIXED is the number of non-&MORE arguments.(define-vop (copy-more-arg)  (:temporary (:sc any-reg :offset nl0-offset) result)  (:temporary (:sc any-reg :offset nl1-offset) count)  (:temporary (:sc any-reg :offset nl2-offset) src)  (:temporary (:sc any-reg :offset nl4-offset) dst)  (:temporary (:sc descriptor-reg :offset l0-offset) temp)  (:info fixed)  (:generator 20    (let ((loop (gen-label))          (do-regs (gen-label))          (done (gen-label)))      (when (< fixed register-arg-count)        ;; Save a pointer to the results so we can fill in register        ;; args. We don't need this if there are more fixed args than        ;; reg args.        (move csp-tn result))      ;; Allocate the space on the stack.      (cond ((zerop fixed)             (inst addq csp-tn nargs-tn csp-tn)             (inst beq nargs-tn done))            (t             (inst subq nargs-tn (fixnumize fixed) count)             (inst ble count done)             (inst addq csp-tn count csp-tn)))      (when (< fixed register-arg-count)        ;; We must stop when we run out of stack args, not when we run        ;; out of &MORE args.        (inst subq nargs-tn (fixnumize register-arg-count) count))      ;; Initialize dst to be end of stack.      (move csp-tn dst)      ;; Everything of interest in registers.      (inst ble count do-regs)      ;; Initialize SRC to be end of args.      (inst addq cfp-tn nargs-tn src)      (emit-label loop)      ;; *--dst = *--src, --count      (inst subq src n-word-bytes src)      (inst subq count (fixnumize 1) count)      (loadw temp src)      (inst subq dst n-word-bytes dst)      (storew temp dst)      (inst bgt count loop)      (emit-label do-regs)      (when (< fixed register-arg-count)        ;; Now we have to deposit any more args that showed up in        ;; registers. We know there is at least one &MORE arg,        ;; otherwise we would have branched to DONE up at the top.        (inst subq nargs-tn (fixnumize (1+ fixed)) count)        (do ((i fixed (1+ i)))            ((>= i register-arg-count))          ;; Store it relative to the pointer saved at the start.          (storew (nth i *register-arg-tns*) result (- i fixed))          ;; Is this the last one?          (inst beq count done)          ;; Decrement count.          (inst subq count (fixnumize 1) count)))      (emit-label done))));;; &MORE args are stored consecutively on the stack, starting;;; immediately at the context pointer. The context pointer is not;;; typed, so the lowtag is 0.(define-full-reffer more-arg * 0 0 (descriptor-reg any-reg) * %more-arg);;; Turn &MORE arg (context, count) into a list.(define-vop (listify-rest-args)  (:args (context-arg :target context :scs (descriptor-reg))         (count-arg :target count :scs (any-reg)))  (:arg-types * tagged-num)  (:temporary (:scs (any-reg) :from (:argument 0)) context)  (:temporary (:scs (any-reg) :from (:argument 1)) count)  (:temporary (:scs (descriptor-reg) :from :eval) temp dst)  (:results (result :scs (descriptor-reg)))  (:translate %listify-rest-args)  (:policy :safe)  (:node-var node)  (:generator 20    (let* ((enter (gen-label))           (loop (gen-label))           (done (gen-label))           (dx-p (node-stack-allocate-p node))           (alloc-area-tn (if dx-p csp-tn alloc-tn)))      (move context-arg context)      (move count-arg count)      ;; Check to see if there are any arguments.      (move null-tn result)      (inst beq count done)      ;; We need to do this atomically.      (pseudo-atomic ()        ;; align CSP        (when dx-p (align-csp temp))        ;; Allocate a cons (2 words) for each item.        (inst bis alloc-area-tn list-pointer-lowtag result)        (move result dst)        (inst sll count 1 temp)        (inst addq alloc-area-tn temp alloc-area-tn)        (inst br zero-tn enter)        ;; Store the current cons in the cdr of the previous cons.        (emit-label loop)        (inst addq dst (* 2 n-word-bytes) dst)        (storew dst dst -1 list-pointer-lowtag)        (emit-label enter)        ;; Grab one value.        (loadw temp context)        (inst addq context n-word-bytes context)        ;; Store the value in the car (in delay slot)        (storew temp dst 0 list-pointer-lowtag)        ;; Decrement count, and if != zero, go back for more.        (inst subq count (fixnumize 1) count)        (inst bne count loop)        ;; NIL out the last cons.        (storew null-tn dst 1 list-pointer-lowtag))      (emit-label done))));;; Return the location and size of the &MORE arg glob created by;;; COPY-MORE-ARG. Supplied is the total number of arguments supplied;;; (originally passed in NARGS.) Fixed is the number of non-&rest;;; arguments.;;;;;; We must duplicate some of the work done by COPY-MORE-ARG, since at;;; that time the environment is in a pretty brain-damaged state,;;; preventing this info from being returned as values. What we do is;;; compute supplied - fixed, and return a pointer that many words;;; below the current stack top.(define-vop (more-arg-context)  (:policy :fast-safe)  (:translate sb!c::%more-arg-context)  (:args (supplied :scs (any-reg)))  (:arg-types tagged-num (:constant fixnum))  (:info fixed)  (:results (context :scs (descriptor-reg))            (count :scs (any-reg)))  (:result-types t tagged-num)  (:note "more-arg-context")  (:generator 5    (inst subq supplied (fixnumize fixed) count)    (inst subq csp-tn count context)));;; Signal wrong argument count error if NARGS isn't equal to COUNT.(define-vop (verify-arg-count)  (:policy :fast-safe)  (:translate sb!c::%verify-arg-count)  (:args (nargs :scs (any-reg)))  (:arg-types positive-fixnum (:constant t))  (:temporary (:scs (any-reg) :type fixnum) temp)  (:info count)  (:vop-var vop)  (:save-p :compute-only)  (:generator 3    (let ((err-lab           (generate-error-code vop invalid-arg-count-error nargs)))      (cond ((zerop count)             (inst bne nargs err-lab))            (t             (inst subq nargs (fixnumize count) temp)             (inst bne temp err-lab))))));;; various other error signalers(macrolet ((frob (name error translate &rest args)             `(define-vop (,name)                ,@(when translate                    `((:policy :fast-safe)                      (:translate ,translate)))                (:args ,@(mapcar (lambda (arg)                                   `(,arg :scs (any-reg descriptor-reg)))                                 args))                (:vop-var vop)                (:save-p :compute-only)                (:generator 1000                  (error-call vop ,error ,@args)))))  (frob arg-count-error invalid-arg-count-error    sb!c::%arg-count-error nargs)  (frob type-check-error object-not-type-error sb!c::%type-check-error    object type)  (frob layout-invalid-error layout-invalid-error sb!c::%layout-invalid-error    object layout)  (frob odd-key-args-error odd-key-args-error    sb!c::%odd-key-args-error)  (frob unknown-key-arg-error unknown-key-arg-error    sb!c::%unknown-key-arg-error key)  (frob nil-fun-returned-error nil-fun-returned-error nil fun));;; Single-stepping(define-vop (step-instrument-before-vop)  (:policy :fast-safe)  (:vop-var vop)  (:generator 3    ;; Stub! See the PPC backend for an example.    (note-this-location vop :step-before-vop)))

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?