(when nfp
(inst addu val nfp (bytes-needed-for-non-descriptor-stack-frame))))))
+;;; Accessing a slot from an earlier stack frame is definite hackery.
+(define-vop (ancestor-frame-ref)
+ (:args (frame-pointer :scs (descriptor-reg))
+ (variable-home-tn :load-if nil))
+ (:results (value :scs (descriptor-reg any-reg)))
+ (:policy :fast-safe)
+ (:generator 4
+ (aver (sc-is variable-home-tn control-stack))
+ (loadw value frame-pointer (tn-offset variable-home-tn))))
+(define-vop (ancestor-frame-set)
+ (:args (frame-pointer :scs (descriptor-reg))
+ (value :scs (descriptor-reg any-reg)))
+ (:results (variable-home-tn :load-if nil))
+ (:policy :fast-safe)
+ (:generator 4
+ (aver (sc-is variable-home-tn control-stack))
+ (storew value frame-pointer (tn-offset variable-home-tn))))
(define-vop (xep-allocate-frame)
(:info start-lab copy-more-arg-follows)
(:generator 1
;; Make sure the function is aligned, and drop a label pointing to this
;; function header.
- (align n-lowtag-bits)
+ (emit-alignment n-lowtag-bits)
(trace-table-entry trace-table-fun-prologue)
(emit-label start-lab)
;; Allocate function header.
(when lra-label
(inst compute-code-from-lra code-tn code-tn lra-label temp))
- (inst addu csp-tn csp-tn 4)
+ (inst addu csp-tn csp-tn n-word-bytes)
(storew (first *register-arg-tns*) csp-tn -1)
- (inst addu start csp-tn -4)
+ (inst addu start csp-tn (- n-word-bytes))
(inst li count (fixnumize 1))
(emit-label done)
step-instrumenting)
(:ignore ,@(unless (or variable (eq return :tail)) '(arg-locs))
- ,@(unless variable '(args))
- ;; Step instrumentation for full calls not implemented yet.
- ;; See the PPC backend for an example.
- step-instrumenting)
+ ,@(unless variable '(args)))
(:temporary (:sc descriptor-reg
:offset ocfp-offset
,@(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)))
- (:temporary (:sc interior-reg :offset lip-offset) entry-point)
+ (:temporary (:sc interior-reg) entry-point)
(:generator ,(+ (if named 5 0)
(if variable 19 1)
(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
(move cfp-tn csp-tn)))
(trace-table-entry trace-table-call-site))))
((nil)
- (inst nop))))))
+ (inst nop)))))
+ (insert-step-instrumenting (callable-tn)
+ ;; Conditionally insert a conditional trap:
+ (when step-instrumenting
+ (load-symbol-value stepping sb!impl::*stepping*)
+ ;; If it's not NIL, trap.
+ (inst beq stepping null-tn step-done-label)
+ (inst nop)
+ ;; CONTEXT-PC will be pointing here when the
+ ;; interrupt is handled, not after the BREAK.
+ (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 break 0 (logior single-step-around-trap
+ (ash (reg-tn-encoding callable-tn)
+ 5)))
+ (emit-label step-done-label))))
,@(if named
`((sc-case name
(- (ash (tn-offset name) word-shift)
other-pointer-lowtag))
(do-next-filler)))
+ ;; The step instrumenting must be done after
+ ;; FUNCTION is loaded, but before ENTRY-POINT is
+ ;; calculated.
+ (insert-step-instrumenting name-pass)
(inst lw entry-point name-pass
(- (ash fdefn-raw-addr-slot word-shift)
other-pointer-lowtag))
(- (ash closure-fun-slot word-shift)
fun-pointer-lowtag))
(do-next-filler)
+ ;; The step instrumenting must be done before
+ ;; after FUNCTION is loaded, but before ENTRY-POINT
+ ;; is calculated.
+ (insert-step-instrumenting function)
(inst addu entry-point function
(- (ash simple-fun-code-offset word-shift)
fun-pointer-lowtag))))
(define-full-reffer more-arg * 0 0 (descriptor-reg any-reg) * %more-arg)
;;; Turn more arg (context, count) into a list.
-(defoptimizer (%listify-rest-args stack-allocate-result) ((&rest args))
- t)
-
(define-vop (listify-rest-args)
(:args (context-arg :target context :scs (descriptor-reg))
(count-arg :target count :scs (any-reg)))
(move context context-arg)
(move count count-arg)
;; Check to see if there are any arguments.
- (inst beq count zero-tn done)
+ (inst beq count done)
(move result null-tn t)
;; We need to do this atomically.
;; Dec count, and if != zero, go back for more.
(inst addu count count (fixnumize -1))
- (inst bne count zero-tn loop)
+ (inst bne count loop)
;; Store the value in the car (in delay slot)
(storew temp dst 0 list-pointer-lowtag)
(let ((err-lab
(generate-error-code vop invalid-arg-count-error nargs)))
(cond ((zerop count)
- (inst bne nargs zero-tn err-lab)
+ (inst bne nargs err-lab)
(inst nop))
(t
(inst li temp (fixnumize count))
;;; Single-stepping
(define-vop (step-instrument-before-vop)
+ (:temporary (:scs (descriptor-reg)) stepping)
(:policy :fast-safe)
(:vop-var vop)
(:generator 3
- ;; Stub! See the PPC backend for an example.
- (note-this-location vop :step-before-vop)))
+ (load-symbol-value stepping sb!impl::*stepping*)
+ ;; If it's not NIL, trap.
+ (inst beq stepping null-tn DONE)
+ (inst nop)
+ ;; CONTEXT-PC will be pointing here when the interrupt is handled,
+ ;; not after the BREAK.
+ (note-this-location vop :step-before-vop)
+ ;; CALLEE-REGISTER-OFFSET isn't needed for before-traps, so we
+ ;; can just use a bare SINGLE-STEP-BEFORE-TRAP as the code.
+ (inst break 0 single-step-before-trap)
+ DONE))