1.0.27.14: bias x86oid frame pointer
authorGabor Melis <mega@hotpop.com>
Tue, 21 Apr 2009 11:25:51 +0000 (11:25 +0000)
committerGabor Melis <mega@hotpop.com>
Tue, 21 Apr 2009 11:25:51 +0000 (11:25 +0000)
Forward port of Alastair Bridgewater's patch.

Duplicate it on x86-64.

Make it so that fp points to ocfp just as if the call had been made by
CALL to a function with the standard prologue "PUSH EBP; MOV ESP,
EBP".

Fix the debugger.

27 files changed:
NEWS
doc/internals/calling-convention.texinfo
src/assembly/x86-64/arith.lisp
src/assembly/x86-64/assem-rtns.lisp
src/assembly/x86/arith.lisp
src/assembly/x86/assem-rtns.lisp
src/code/debug-int.lisp
src/compiler/x86-64/call.lisp
src/compiler/x86-64/char.lisp
src/compiler/x86-64/debug.lisp
src/compiler/x86-64/float.lisp
src/compiler/x86-64/insts.lisp
src/compiler/x86-64/move.lisp
src/compiler/x86-64/nlx.lisp
src/compiler/x86-64/sap.lisp
src/compiler/x86-64/static-fn.lisp
src/compiler/x86-64/type-vops.lisp
src/compiler/x86-64/vm.lisp
src/compiler/x86/call.lisp
src/compiler/x86/debug.lisp
src/compiler/x86/nlx.lisp
src/compiler/x86/static-fn.lisp
src/compiler/x86/vm.lisp
src/runtime/backtrace.c
src/runtime/x86-64-assem.S
src/runtime/x86-assem.S
version.lisp-expr

diff --git a/NEWS b/NEWS
index fe81cbb..6f89262 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ changes in sbcl-1.0.28 relative to 1.0.27:
   * bug fix: RESTART-FRAME and RETURN-FROM-FRAME stack corruption
   * bug fix: the discriminating function for PRINT-OBJECT no longer preserves
     potentially-invalid effective methods in its cache.
+  * improvement: on x86/x86-64 Lisp call frames now have the same layout as C
+    frames, allowing for instance more reliable backtraces.
 
 changes in sbcl-1.0.27 relative to 1.0.26:
   * new port: support added for x86-64 OpenBSD. (thanks to Josh Elsasser)
index bf5b2f3..5fcb529 100644 (file)
@@ -119,7 +119,39 @@ frame to include sufficient space for its local variables, after
 possibly converting any @code{&rest} arguments to a proper list.
 
 The above scheme was changed in 1.0.27 on x86 and x86-64 by swapping
-the old frame pointer and the return address.
+the old frame pointer with the return address and making EBP point two
+words later:
+
+On x86/x86-64 the stack now looks like this (stack grows downwards):
+
+@verbatim
+----------
+RETURN PC
+----------
+OLD FP
+---------- <- FP points here
+EMPTY SLOT
+----------
+FIRST ARG
+----------
+@end verbatim
+
+just as if the function had been CALLed and upon entry executed the
+standard prologue: PUSH EBP; MOV EBP, ESP. On other architectures the
+stack looks like this (stack grows upwards):
+
+@verbatim
+----------
+FIRST ARG
+----------
+EMPTY SLOT
+----------
+RETURN PC
+----------
+OLD FP
+---------- <- FP points here
+@end verbatim
+
 
 @node Unknown-Values Returns
 @comment  node-name,  next,  previous,  up
index b6a1934..fc05cbe 100644 (file)
                 (inst ret)
 
                 DO-STATIC-FUN
+                ;; Same as: (inst enter (fixnumize 1))
                 (inst push rbp-tn)
-                (inst lea rbp-tn (make-ea :qword
-                                          :base rsp-tn
-                                          :disp (* 2 n-word-bytes)))
+                (inst mov rbp-tn rsp-tn)
                 (inst sub rsp-tn (fixnumize 1))
-                (inst push (make-ea :qword :base rbp-tn :disp (- n-word-bytes)))
+                (inst push (make-ea :qword :base rbp-tn
+                            :disp (frame-byte-offset return-pc-save-offset)))
                 (inst mov rcx (fixnumize 2)) ; arg count
                 (inst jmp
                       (make-ea :qword
   (inst jmp :z FIXNUM)
 
   (inst push rbp-tn)
-  (inst lea rbp-tn (make-ea :qword :base rsp-tn :disp (* 2 n-word-bytes)))
+  (inst mov rbp-tn rsp-tn)
   (inst sub rsp-tn (fixnumize 1))
-  (inst push (make-ea :qword :base rbp-tn :disp (- n-word-bytes)))
+  (inst push (make-ea :qword :base rbp-tn
+                      :disp (frame-byte-offset return-pc-save-offset)))
   (inst mov rcx (fixnumize 1))    ; arg count
   (inst jmp (make-ea :qword
                      :disp (+ nil-value (static-fun-offset '%negate))))
                 (inst ret)
 
                 DO-STATIC-FUN
-                (move rcx rsp-tn)
                 (inst sub rsp-tn (fixnumize 3))
-                (inst mov (make-ea :qword
-                                   :base rcx
-                                   :disp (frame-byte-offset ocfp-save-offset))
+                (inst mov (make-ea :qword :base rsp-tn
+                                   :disp (frame-byte-offset
+                                          (+ sp->fp-offset
+                                             -3
+                                             ocfp-save-offset)))
                       rbp-tn)
-                (move rbp-tn rcx)
+                (inst lea rbp-tn (make-ea :qword :base rsp-tn
+                                          :disp (frame-byte-offset
+                                          (+ sp->fp-offset
+                                             -3
+                                             ocfp-save-offset))))
                 (inst mov rcx (fixnumize 2))
                 (inst call (make-ea :qword
                                     :disp (+ nil-value
   (inst ret)
 
   DO-STATIC-FUN
-  (move rcx rsp-tn)
   (inst sub rsp-tn (fixnumize 3))
-  (inst mov (make-ea :qword
-                     :base rcx
-                     :disp (frame-byte-offset ocfp-save-offset))
+  (inst mov (make-ea :qword :base rsp-tn
+                     :disp (frame-byte-offset
+                            (+ sp->fp-offset
+                               -3
+                               ocfp-save-offset)))
         rbp-tn)
-  (move rbp-tn rcx)
+  (inst lea rbp-tn (make-ea :qword :base rsp-tn
+                            :disp (frame-byte-offset
+                                   (+ sp->fp-offset
+                                      -3
+                                      ocfp-save-offset))))
   (inst mov rcx (fixnumize 2))
   (inst call (make-ea :qword
                       :disp (+ nil-value (static-fun-offset 'eql))))
   (inst ret)
 
   DO-STATIC-FUN
-  (move rcx rsp-tn)
   (inst sub rsp-tn (fixnumize 3))
-  (inst mov (make-ea :qword
-                     :base rcx
-                     :disp (frame-byte-offset ocfp-save-offset))
+  (inst mov (make-ea :qword :base rsp-tn
+                     :disp (frame-byte-offset
+                            (+ sp->fp-offset
+                               -3
+                               ocfp-save-offset)))
         rbp-tn)
-  (move rbp-tn rcx)
+  (inst lea rbp-tn (make-ea :qword :base rsp-tn
+                            :disp (frame-byte-offset
+                                   (+ sp->fp-offset
+                                      -3
+                                      ocfp-save-offset))))
+
   (inst mov rcx (fixnumize 2))
   (inst call (make-ea :qword
                       :disp (+ nil-value (static-fun-offset 'two-arg-=))))
index 5b51eef..28b0c1c 100644 (file)
   (inst cmp ecx (fixnumize 3))
   (inst jmp :e THREE-VALUES)
 
-  (inst mov ebx rbp-tn)
-  ;; Save the count, because the loop is going to destroy it.
+  ;; As per the calling convention EBX is expected to point at the SP
+  ;; before the stack frame.
+  (inst lea ebx (make-ea :qword :base rbp-tn
+                         :disp (* sp->fp-offset n-word-bytes)))
+
+  ;; Save the count, the return address and restore the frame pointer,
+  ;; because the loop is going to destroy them.
   (inst mov edx ecx)
   (inst mov eax (make-ea :qword :base rbp-tn
                          :disp (frame-byte-offset return-pc-save-offset)))
 
   ;; Handle the register arg cases.
   ZERO-VALUES
-  (inst mov ebx rbp-tn)
+  (inst lea ebx (make-ea :qword :base rbp-tn
+                         :disp (* sp->fp-offset n-word-bytes)))
   (inst mov edx nil-value)
   (inst mov edi edx)
   (inst mov esi edx)
-  (inst lea rsp-tn
-        (make-ea :qword :base ebx
-                 :disp (frame-byte-offset ocfp-save-offset)))
+  (inst mov rsp-tn rbp-tn)
   (inst stc)
   (inst pop rbp-tn)
   (inst ret)
   ;; check for this case when size > speed.
   ONE-VALUE
   (loadw edx esi -1)
-  (inst lea rsp-tn
-        (make-ea :qword :base rbp-tn
-                 :disp (frame-byte-offset ocfp-save-offset)))
+  (inst mov rsp-tn rbp-tn)
   (inst clc)
   (inst pop rbp-tn)
   (inst ret)
 
   TWO-VALUES
-  (inst mov ebx rbp-tn)
+  (inst lea ebx (make-ea :qword :base rbp-tn
+                         :disp (* sp->fp-offset n-word-bytes)))
   (loadw edx esi -1)
   (loadw edi esi -2)
   (inst mov esi nil-value)
-  (inst lea rsp-tn
-        (make-ea :qword :base ebx
-                 :disp (frame-byte-offset ocfp-save-offset)))
+  (inst mov rsp-tn rbp-tn)
   (inst stc)
   (inst pop rbp-tn)
   (inst ret)
 
   THREE-VALUES
-  (inst mov ebx rbp-tn)
+  (inst lea ebx (make-ea :qword :base rbp-tn
+                         :disp (* sp->fp-offset n-word-bytes)))
   (loadw edx esi -1)
   (loadw edi esi -2)
   (loadw esi esi -3)
-  (inst lea rsp-tn
-        (make-ea :qword :base ebx
-                 :disp (frame-byte-offset ocfp-save-offset)))
+  (inst mov rsp-tn rbp-tn)
   (inst stc)
   (inst pop rbp-tn)
   (inst ret))
 
   ;; Clear most of the stack.
   (inst lea rsp-tn
-        (make-ea :qword :base rbp-tn :disp (* -3 n-word-bytes)))
+        (make-ea :qword :base rbp-tn :disp (* (- sp->fp-offset 3) n-word-bytes)))
 
   ;; Push the return-pc so it looks like we just called.
   (pushw rbp-tn (frame-word-offset return-pc-save-offset))
index 28d510f..54f9489 100644 (file)
                 (inst ret)
 
                 DO-STATIC-FUN
+                ;; Same as: (inst enter (fixnumize 1))
                 (inst push ebp-tn)
-                (inst lea ebp-tn (make-ea :dword
-                                          :base esp-tn
-                                          :disp (* 2 n-word-bytes)))
+                (inst mov ebp-tn esp-tn)
                 (inst sub esp-tn (fixnumize 1))
-                (inst push (make-ea :dword :base ebp-tn :disp (- n-word-bytes)))
+                (inst push (make-ea :dword :base ebp-tn
+                            :disp (frame-byte-offset return-pc-save-offset)))
                 (inst mov ecx (fixnumize 2)) ; arg count
                 (inst jmp
                       (make-ea :dword
   (inst jmp :z FIXNUM)
 
   (inst push ebp-tn)
-  (inst lea ebp-tn (make-ea :dword :base esp-tn :disp (* 2 n-word-bytes)))
+  (inst mov ebp-tn esp-tn)
   (inst sub esp-tn (fixnumize 1))
-  (inst push (make-ea :dword :base ebp-tn :disp (- n-word-bytes)))
+  (inst push (make-ea :dword :base ebp-tn
+                      :disp (frame-byte-offset return-pc-save-offset)))
   (inst mov ecx (fixnumize 1))    ; arg count
   (inst jmp (make-ea :dword
                      :disp (+ nil-value (static-fun-offset '%negate))))
                 (inst ret)
 
                 DO-STATIC-FUN
-                (move ecx esp-tn)
                 (inst sub esp-tn (fixnumize 3))
-                (inst mov (make-ea :dword
-                                   :base ecx
-                                   :disp (frame-byte-offset ocfp-save-offset))
+                (inst mov (make-ea :dword :base esp-tn
+                                   :disp (frame-byte-offset
+                                          (+ sp->fp-offset
+                                             -3
+                                             ocfp-save-offset)))
                       ebp-tn)
-                (move ebp-tn ecx)
+                (inst lea ebp-tn (make-ea :dword :base esp-tn
+                                          :disp (frame-byte-offset
+                                          (+ sp->fp-offset
+                                             -3
+                                             ocfp-save-offset))))
                 (inst mov ecx (fixnumize 2))
                 (inst call (make-ea :dword
                                     :disp (+ nil-value
   (inst cmp ecx other-pointer-lowtag)
   (inst jmp :e DO-STATIC-FUN)
 
-  ;; Not both other pointers
+  ;; At least one fixnum
   (inst cmp x y)
   RET
   (inst ret)
   (inst cmp x y)
   (inst jmp :e RET)
 
-  (move ecx esp-tn)
   (inst sub esp-tn (fixnumize 3))
-  (inst mov (make-ea :dword
-                     :base ecx
-                     :disp (frame-byte-offset ocfp-save-offset))
+  (inst mov (make-ea :dword :base esp-tn
+                     :disp (frame-byte-offset
+                            (+ sp->fp-offset
+                               -3
+                               ocfp-save-offset)))
         ebp-tn)
-  (move ebp-tn ecx)
+  (inst lea ebp-tn (make-ea :dword :base esp-tn
+                            :disp (frame-byte-offset
+                                   (+ sp->fp-offset
+                                      -3
+                                      ocfp-save-offset))))
   (inst mov ecx (fixnumize 2))
   (inst call (make-ea :dword
                       :disp (+ nil-value (static-fun-offset 'eql))))
   (inst ret)
 
   DO-STATIC-FUN
-  (move ecx esp-tn)
   (inst sub esp-tn (fixnumize 3))
-  (inst mov (make-ea :dword
-                     :base ecx
-                     :disp (frame-byte-offset ocfp-save-offset))
+  (inst mov (make-ea :dword :base esp-tn
+                     :disp (frame-byte-offset
+                            (+ sp->fp-offset
+                               -3
+                               ocfp-save-offset)))
         ebp-tn)
-  (move ebp-tn ecx)
+  (inst lea ebp-tn (make-ea :dword :base esp-tn
+                            :disp (frame-byte-offset
+                                   (+ sp->fp-offset
+                                      -3
+                                      ocfp-save-offset))))
   (inst mov ecx (fixnumize 2))
   (inst call (make-ea :dword
                       :disp (+ nil-value (static-fun-offset 'two-arg-=))))
index ee8a506..cce719e 100644 (file)
   (inst cmp ecx (fixnumize 3))
   (inst jmp :e THREE-VALUES)
 
-  (inst mov ebx ebp-tn)
-  ;; Save the count, because the loop is going to destroy it.
+  ;; As per the calling convention EBX is expected to point at the SP
+  ;; before the stack frame.
+  (inst lea ebx (make-ea :dword :base ebp-tn
+                         :disp (* sp->fp-offset n-word-bytes)))
+
+  ;; Save the count, the return address and restore the frame pointer,
+  ;; because the loop is going to destroy them.
   (inst mov edx ecx)
   (inst mov eax (make-ea :dword :base ebp-tn
                          :disp (frame-byte-offset return-pc-save-offset)))
 
   ;; Handle the register arg cases.
   ZERO-VALUES
-  (inst mov ebx ebp-tn)
+  (inst lea ebx (make-ea :dword :base ebp-tn
+                         :disp (* sp->fp-offset n-word-bytes)))
   (inst mov edx nil-value)
   (inst mov edi edx)
   (inst mov esi edx)
-  (inst lea esp-tn
-        (make-ea :dword :base ebx
-                 :disp (frame-byte-offset ocfp-save-offset)))
+  (inst mov esp-tn ebp-tn)
   (inst stc)
   (inst pop ebp-tn)
   (inst ret)
   ;; check for this case when size > speed.
   ONE-VALUE
   (loadw edx esi -1)
-  (inst lea esp-tn
-        (make-ea :dword :base ebp-tn
-                 :disp (frame-byte-offset ocfp-save-offset)))
+  (inst mov esp-tn ebp-tn)
   (inst clc)
   (inst pop ebp-tn)
   (inst ret)
 
   TWO-VALUES
-  (inst mov ebx ebp-tn)
+  (inst lea ebx (make-ea :dword :base ebp-tn
+                         :disp (* sp->fp-offset n-word-bytes)))
   (loadw edx esi -1)
   (loadw edi esi -2)
   (inst mov esi nil-value)
-  (inst lea esp-tn
-        (make-ea :dword :base ebx
-                 :disp (frame-byte-offset ocfp-save-offset)))
+  (inst mov esp-tn ebp-tn)
   (inst stc)
   (inst pop ebp-tn)
   (inst ret)
 
   THREE-VALUES
-  (inst mov ebx ebp-tn)
+  (inst lea ebx (make-ea :dword :base ebp-tn
+                         :disp (* sp->fp-offset n-word-bytes)))
   (loadw edx esi -1)
   (loadw edi esi -2)
   (loadw esi esi -3)
-  (inst lea esp-tn
-        (make-ea :dword :base ebx
-                 :disp (frame-byte-offset ocfp-save-offset)))
+  (inst mov esp-tn ebp-tn)
   (inst stc)
   (inst pop ebp-tn)
   (inst ret))
 
   ;; Clear most of the stack.
   (inst lea esp-tn
-        (make-ea :dword :base ebp-tn :disp (* -3 n-word-bytes)))
+        (make-ea :dword :base ebp-tn :disp (* (- sp->fp-offset 3) n-word-bytes)))
 
   ;; Push the return-pc so it looks like we just called.
   (pushw ebp-tn (frame-word-offset return-pc-save-offset))
index e5dfe62..d003425 100644 (file)
                             (- (get-lisp-obj-address code)
                                sb!vm:other-pointer-lowtag)
                             code-header-len)))
-;        (format t "c-lra-fpc ~A ~A ~A~%" pc code pc-offset)
+         ;;(format t "c-lra-fpc ~A ~A ~A~%" pc code pc-offset)
          (values pc-offset code)))))
 
 #!+(or x86 x86-64)
 (declaim (maybe-inline x86-call-context))
 (defun x86-call-context (fp)
   (declare (type system-area-pointer fp))
-  (labels ((fail ()
-             (values nil
-                     (int-sap 0)
-                     (int-sap 0)))
-           (handle (fp)
-             (cond
-               ((not (control-stack-pointer-valid-p fp))
-                (fail))
-               (t
-                ;; Check the two possible frame pointers.
-                (let ((lisp-ocfp (sap-ref-sap fp (- (* (1+ ocfp-save-offset)
-                                                       sb!vm::n-word-bytes))))
-                      (lisp-ra (sap-ref-sap fp (- (* (1+ return-pc-save-offset)
-                                                     sb!vm::n-word-bytes))))
-                      (c-ocfp (sap-ref-sap fp (* 0 sb!vm:n-word-bytes)))
-                      (c-ra (sap-ref-sap fp (* 1 sb!vm:n-word-bytes))))
-                  (cond ((and (sap> lisp-ocfp fp)
-                              (control-stack-pointer-valid-p lisp-ocfp)
-                              (ra-pointer-valid-p lisp-ra)
-                              (sap> c-ocfp fp)
-                              (control-stack-pointer-valid-p c-ocfp)
-                              (ra-pointer-valid-p c-ra))
-                         ;; Look forward another step to check their validity.
-                         (let ((lisp-ok (handle lisp-ocfp))
-                               (c-ok (handle c-ocfp)))
-                           (cond ((and lisp-ok c-ok)
-                                  ;; Both still seem valid - choose the lisp frame.
-                                  #!+freebsd
-                                  (if (sap> lisp-ocfp c-ocfp)
-                                      (values t lisp-ra lisp-ocfp)
-                                      (values t c-ra c-ocfp))
-                                  #!-freebsd
-                                  (values t lisp-ra lisp-ocfp))
-                                 (lisp-ok
-                                  ;; The lisp convention is looking good.
-                                  (values t lisp-ra lisp-ocfp))
-                                 (c-ok
-                                  ;; The C convention is looking good.
-                                  (values t c-ra c-ocfp))
-                                 (t
-                                  ;; Neither seems right?
-                                  (fail)))))
-                        ((and (sap> lisp-ocfp fp)
-                              (control-stack-pointer-valid-p lisp-ocfp)
-                              (ra-pointer-valid-p lisp-ra))
-                         ;; The lisp convention is looking good.
-                         (values t lisp-ra lisp-ocfp))
-                        ((and (sap> c-ocfp fp)
-                              (control-stack-pointer-valid-p c-ocfp)
-                              #!-linux (ra-pointer-valid-p c-ra))
-                         ;; The C convention is looking good.
-                         (values t c-ra c-ocfp))
-                        (t
-                         (fail))))))))
-    (handle fp)))
+  (let ((ocfp (sap-ref-sap fp (sb!vm::frame-byte-offset ocfp-save-offset)))
+        (ra (sap-ref-sap fp (sb!vm::frame-byte-offset return-pc-save-offset))))
+    (if (and (control-stack-pointer-valid-p fp)
+             (sap> ocfp fp)
+             (control-stack-pointer-valid-p ocfp)
+             (ra-pointer-valid-p ra))
+        (values t ra ocfp)
+        (values nil (int-sap 0) (int-sap 0)))))
 
 ) ; #+x86 PROGN
 \f
           (#.ocfp-save-offset
            (stack-ref pointer stack-slot))
           (#.lra-save-offset
-           (sap-ref-sap pointer (- (* (1+ stack-slot)
-                                      sb!vm::n-word-bytes))))))))
+           (sap-ref-sap pointer (sb!vm::frame-byte-offset stack-slot)))))))
 
 (defun (setf get-context-value) (value frame stack-slot loc)
   (declare (type compiled-frame frame) (type unsigned-byte stack-slot)
           (#.ocfp-save-offset
            (setf (stack-ref pointer stack-slot) value))
           (#.lra-save-offset
-           (setf (sap-ref-sap pointer (- (* (1+ stack-slot)
-                                            sb!vm::n-word-bytes))) value))))))
+           (setf (sap-ref-sap pointer (sb!vm::frame-byte-offset stack-slot))
+                 value))))))
 
 (defun foreign-function-backtrace-name (sap)
   (let ((name (sap-foreign-symbol sap)))
@@ -2102,8 +2054,9 @@ register."
                   ,@body))
              (stack-frame-offset (data-width offset)
                #!+(or x86 x86-64)
-               `(- (* (+ (sb!c:sc-offset-offset sc-offset) ,data-width ,offset)
-                      sb!vm:n-word-bytes))
+               `(sb!vm::frame-byte-offset (+ (sb!c:sc-offset-offset sc-offset)
+                                           (1- ,data-width)
+                                           ,offset))
                #!-(or x86 x86-64)
                (declare (ignore data-width))
                #!-(or x86 x86-64)
@@ -2289,8 +2242,9 @@ register."
                   ,@body))
              (stack-frame-offset (data-width offset)
                #!+(or x86 x86-64)
-               `(- (* (+ (sb!c:sc-offset-offset sc-offset) ,data-width ,offset)
-                      sb!vm:n-word-bytes))
+               `(sb!vm::frame-byte-offset (+ (sb!c:sc-offset-offset sc-offset)
+                                           (1- ,data-width)
+                                           ,offset))
                #!-(or x86 x86-64)
                (declare (ignore data-width))
                #!-(or x86 x86-64)
index 13a4511..2e07954 100644 (file)
       (inst lea rsp-tn
             (make-ea :qword :base rbp-tn
                      :disp (- (* n-word-bytes
-                                 (max 3 (sb-allocated-size 'stack)))))))
+                                 (- (max 3 (sb-allocated-size 'stack))
+                                    sp->fp-offset))))))
 
     (trace-table-entry trace-table-normal)))
 
 ;;; or a multiple-call-local. All it does is allocate stack space for the
 ;;; callee (who has the same size stack as us).
 (define-vop (allocate-frame)
-  (:results (res :scs (any-reg control-stack))
+  (:results (res :scs (any-reg))
             (nfp))
   (:info callee)
   (:ignore nfp callee)
   (:generator 2
-    (move res rsp-tn)
+    (inst lea res (make-ea :qword :base rsp-tn
+                           :disp (- (* sp->fp-offset n-word-bytes))))
     (inst sub rsp-tn (* n-word-bytes (sb-allocated-size 'stack)))))
 
 ;;; Allocate a partial frame for passing stack arguments in a full
 ;;; before it can extend the stack.
 (define-vop (allocate-full-call-frame)
   (:info nargs)
-  (:results (res :scs (any-reg control-stack)))
+  (:results (res :scs (any-reg)))
   (:generator 2
-    (move res rsp-tn)
+    (inst lea res (make-ea :qword :base rsp-tn
+                           :disp (- (* sp->fp-offset n-word-bytes))))
     (inst sub rsp-tn (* (max nargs 3) n-word-bytes))))
 \f
 ;;; Emit code needed at the return-point from an unknown-values call
             (when first-stack-arg-p
               ;; There are stack args so the frame of the callee is
               ;; still there, save RDX in its first slot temporalily.
-              (storew rdx-tn rbx-tn -1))
-            (loadw rdx-tn rbx-tn (frame-word-offset i))
+              (storew rdx-tn rbx-tn (frame-word-offset sp->fp-offset)))
+            (loadw rdx-tn rbx-tn (frame-word-offset (+ sp->fp-offset i)))
             (inst mov tn rdx-tn)))
 
         (emit-label defaulting-done)
-        (loadw rdx-tn rbx-tn -1)
+        (loadw rdx-tn rbx-tn (frame-word-offset sp->fp-offset))
         (move rsp-tn rbx-tn)
 
         (let ((defaults (defaults)))
       ;; and then default the remaining stack arguments.
       (emit-label regs-defaulted)
       ;; Save EDI.
-      (storew rdi-tn rbx-tn (frame-word-offset 1))
+      (storew rdi-tn rbx-tn (frame-word-offset (+ sp->fp-offset 1)))
       ;; Compute the number of stack arguments, and if it's zero or
       ;; less, don't copy any stack arguments.
       (inst sub rcx-tn (fixnumize register-arg-count))
             (make-ea :qword :base rbp-tn
                      :disp (frame-byte-offset register-arg-count)))
       ;; Save ESI, and compute a pointer to where the args come from.
-      (storew rsi-tn rbx-tn (frame-word-offset 2))
+      (storew rsi-tn rbx-tn (frame-word-offset (+ sp->fp-offset 2)))
       (inst lea rsi-tn
             (make-ea :qword :base rbx-tn
-                     :disp (frame-byte-offset register-arg-count)))
+                     :disp (frame-byte-offset
+                            (+ sp->fp-offset register-arg-count))))
       ;; Do the copy.
       (inst shr rcx-tn word-shift)              ; make word count
       (inst std)
       (inst rep)
       (inst movs :qword)
       ;; Restore RSI.
-      (loadw rsi-tn rbx-tn (frame-word-offset 2))
+      (loadw rsi-tn rbx-tn (frame-word-offset (+ sp->fp-offset 2)))
       ;; Now we have to default the remaining args. Find out how many.
       (inst sub rax-tn (fixnumize (- nvals register-arg-count)))
       (inst neg rax-tn)
       (inst stos rax-tn)
       ;; Restore EDI, and reset the stack.
       (emit-label restore-edi)
-      (loadw rdi-tn rbx-tn (frame-word-offset 1))
+      (loadw rdi-tn rbx-tn (frame-word-offset (+ sp->fp-offset 1)))
       (inst mov rsp-tn rbx-tn)
       (inst cld))))
   (values))
     (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
     ;; Zot all of the stack except for the old-fp and return-pc.
-    (inst lea rsp-tn
-          (make-ea :qword :base rbp-tn
-                   :disp (frame-byte-offset ocfp-save-offset)))
+    (inst mov rsp-tn rbp-tn)
     (inst pop rbp-tn)
     (inst ret)
     (trace-table-entry trace-table-normal)))
                           ,(if variable
                                '(inst sub rsp-tn (fixnumize 3)))
 
+                          ;; Bias the new-fp for use as an fp
+                          ,(if variable
+                               '(inst sub new-fp (fixnumize sp->fp-offset)))
+
                           ;; Save the fp
                           (storew rbp-tn new-fp
                                   (frame-word-offset ocfp-save-offset))
     (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
     ;; Drop stack above old-fp
-    (inst lea rsp-tn (make-ea :qword :base rbp-tn
-                              :disp (frame-byte-offset (tn-offset old-fp))))
+    (inst mov rsp-tn rbp-tn)
     ;; Clear the multiple-value return flag
     (inst clc)
     ;; Restore the old frame pointer
       (error "nvalues is 1"))
     (trace-table-entry trace-table-fun-epilogue)
     ;; Establish the values pointer and values count.
-    (move rbx rbp-tn)
+    (inst lea rbx (make-ea :qword :base rbp-tn
+                           :disp (* sp->fp-offset n-word-bytes)))
     (if (zerop nvals)
         (zeroize rcx) ; smaller
         (inst mov rcx (fixnumize nvals)))
-    ;; Clear as much of the stack as possible, but not past the old
-    ;; frame address.
-    (inst lea rsp-tn
-          (make-ea :qword :base rbx
-                   :disp (frame-byte-offset
-                          (if (< register-arg-count nvals)
-                              (1- nvals)
-                              ocfp-save-offset))))
     ;; Pre-default any argument register that need it.
     (when (< nvals register-arg-count)
       (let* ((arg-tns (nthcdr nvals (list a0 a1 a2)))
     ;; stack and we've changed the stack pointer. So we have to
     ;; tell it to index off of RBX instead of RBP.
     (cond ((<= nvals register-arg-count)
+           (inst mov rsp-tn rbp-tn)
            (inst pop rbp-tn)
            (inst ret))
           (t
            ;; Some values are on the stack after RETURN-PC and OLD-FP,
            ;; can't return normally and some slots of the frame will
            ;; be used as temporaries by the receiver.
+           ;;
+           ;; Clear as much of the stack as possible, but not past the
+           ;; old frame address.
+           (inst lea rsp-tn
+                 (make-ea :qword :base rbp-tn
+                          :disp (frame-byte-offset (1- nvals))))
            (move rbp-tn old-fp)
            (inst push (make-ea :qword :base rbx
-                               :disp (frame-byte-offset (tn-offset return-pc))))
+                               :disp (frame-byte-offset
+                                      (+ sp->fp-offset
+                                         (tn-offset return-pc)))))
            (inst ret)))
 
     (trace-table-entry trace-table-normal)))
 ;;; assembly-routine.
 ;;;
 ;;; The assembly routine takes the following args:
-;;;  RAX -- the return-pc to finally jump to.
-;;;  RBX -- pointer to where to put the values.
 ;;;  RCX -- number of values to find there.
 ;;;  RSI -- pointer to where to find the values.
 (define-vop (return-multiple)
         (inst jmp :ne not-single)
         ;; Return with one value.
         (loadw a0 vals -1)
-        (inst lea rsp-tn (make-ea :qword :base rbp-tn
-                                  :disp (frame-byte-offset ocfp-save-offset)))
+        ;; Clear the stack until ocfp.
+        (inst mov rsp-tn rbp-tn)
         ;; clear the multiple-value return flag
         (inst clc)
         ;; Out of here.
            (inst jmp :be JUST-ALLOC-FRAME)))
 
     ;; Allocate the space on the stack.
-    ;; stack = rbp - (max 3 frame-size) - (nargs - fixed)
+    ;; stack = rbp + sp->fp-offset - (max 3 frame-size) - (nargs - fixed)
     (inst lea rbx-tn
           (make-ea :qword :base rbp-tn
-                   :disp (- (fixnumize fixed)
-                            (* n-word-bytes
+                   :disp (* n-word-bytes
+                            (- (+ sp->fp-offset fixed)
                                (max 3 (sb-allocated-size 'stack))))))
     (inst sub rbx-tn rcx-tn)  ; Got the new stack in rbx
     (inst mov rsp-tn rbx-tn)
            (inst sub rcx-tn (fixnumize fixed))))
 
     ;; Initialize R8 to be the end of args.
-    (inst mov source rbp-tn)
+    (inst lea source (make-ea :qword :base rbp-tn
+                              :disp (* sp->fp-offset n-word-bytes)))
     (inst sub source rbx-tn)
 
     ;; We need to copy from downwards up to avoid overwriting some of
           ( nil )
         ;; Store it relative to rbp
         (inst mov (make-ea :qword :base rbp-tn
-                           :disp (- (* n-word-bytes
-                                       (+ 1 (- i fixed)
-                                          (max 3 (sb-allocated-size 'stack))))))
+                           :disp (* n-word-bytes
+                                    (- sp->fp-offset
+                                       (+ 1
+                                          (- i fixed)
+                                          (max 3 (sb-allocated-size
+                                                  'stack))))))
               (nth i *register-arg-tns*))
 
         (incf i)
     JUST-ALLOC-FRAME
     (inst lea rsp-tn
           (make-ea :qword :base rbp-tn
-                   :disp (- (* n-word-bytes
+                   :disp (* n-word-bytes
+                            (- sp->fp-offset
                                (max 3 (sb-allocated-size 'stack))))))
 
     DONE))
index 8e92290..b70458c 100644 (file)
       (character-stack
        #!-sb-unicode
        (inst mov
-             ;; FIXME: naked 8 (should be... what?  n-register-bytes?
-             ;; n-word-bytes?  Dunno.
-             (make-ea :byte :base fp :disp (- (* (1+ (tn-offset y)) 8)))
+             ;; XXX: If the sb-unicode case needs to handle c-call,
+             ;; why does the non-unicode case not need to?
+             (make-ea :byte :base fp :disp (frame-byte-offset (tn-offset y)))
              x)
        #!+sb-unicode
        (if (= (tn-offset fp) esp-offset)
-           (storew x fp (tn-offset y)) ; c-call
-           (storew x fp (- (1+ (tn-offset y)))))))))
+           (storew x fp (tn-offset y))  ; c-call
+           (storew x fp (frame-word-offset (tn-offset y))))))))
 (define-move-vop move-character-arg :move-arg
   (any-reg character-reg) (character-reg))
 
index 5ab67c6..5f720fe 100644 (file)
@@ -43,7 +43,7 @@
     (move temp offset)
     (inst neg temp)
     (inst mov result
-          (make-ea :qword :base sap :disp (- n-word-bytes) :index temp))))
+          (make-ea :qword :base sap :disp (frame-byte-offset 0) :index temp))))
 
 (define-vop (read-control-stack-c)
   (:translate stack-ref)
@@ -55,7 +55,7 @@
   (:result-types *)
   (:generator 5
     (inst mov result (make-ea :qword :base sap
-                              :disp (- (* (1+ index) n-word-bytes))))))
+                              :disp (frame-byte-offset index)))))
 
 (define-vop (write-control-stack)
   (:translate %set-stack-ref)
@@ -71,7 +71,8 @@
     (move temp offset)
     (inst neg temp)
     (inst mov
-          (make-ea :qword :base sap :disp (- n-word-bytes) :index temp) value)
+          (make-ea :qword :base sap :disp (frame-byte-offset 0) :index temp)
+          value)
     (move result value)))
 
 (define-vop (write-control-stack-c)
@@ -84,8 +85,7 @@
   (:results (result :scs (descriptor-reg)))
   (:result-types *)
   (:generator 5
-    (inst mov (make-ea :qword :base sap
-                       :disp (- (* (1+ index) n-word-bytes)))
+    (inst mov (make-ea :qword :base sap :disp (frame-byte-offset index))
           value)
     (move result value)))
 
index b642b5c..23eef99 100644 (file)
@@ -32,8 +32,7 @@
              (declare (ignore kind))
              `(make-ea
                :qword :base rbp-tn
-               :disp (- (* (+ (tn-offset ,tn) 1)
-                           n-word-bytes)))))
+               :disp (frame-byte-offset (tn-offset ,tn)))))
   (defun ea-for-sf-stack (tn)
     (ea-for-xf-stack tn :single))
   (defun ea-for-df-stack (tn)
              (declare (ignore kind))
              `(make-ea
                :qword :base ,base
-               :disp (- (* (+ (tn-offset ,tn)
-                              (* 1 (ecase ,slot (:real 1) (:imag 2))))
-                           n-word-bytes)))))
+               :disp (frame-byte-offset
+                      (+ (tn-offset ,tn)
+                       (cond ((= (tn-offset ,base) rsp-offset)
+                              sp->fp-offset)
+                             ((= (tn-offset ,base) rbp-offset)
+                              0)
+                             (t (error "Unexpected offset.")))
+                       (ecase ,slot (:real 0) (:imag 1)))))))
   (defun ea-for-csf-real-stack (tn &optional (base rbp-tn))
     (ea-for-cxf-stack tn :single :real base))
   (defun ea-for-csf-imag-stack (tn &optional (base rbp-tn))
                                       (:double '((inst movsd ea x)))))
                            (let ((ea (make-ea
                                       :dword :base fp
-                                      :disp (- (* (1+ (tn-offset y))
-                                                  n-word-bytes)))))
+                                      :disp (frame-byte-offset (tn-offset y)))))
                              ,@(ecase format
                                  (:single '((inst movss ea x)))
                                  (:double '((inst movsd ea x))))))))))
         (inst movsd temp float)
         (move hi-bits temp))
        (double-stack
-        (loadw hi-bits ebp-tn (- (1+ (tn-offset float)))))
+        (loadw hi-bits ebp-tn (frame-word-offset (tn-offset float))))
        (descriptor-reg
         (loadw hi-bits float double-float-value-slot
                other-pointer-lowtag)))
         (inst movsd temp float)
         (move lo-bits temp))
        (double-stack
-        (loadw lo-bits ebp-tn (- (1+ (tn-offset float)))))
+        (loadw lo-bits ebp-tn (frame-word-offset (tn-offset float))))
        (descriptor-reg
         (loadw lo-bits float double-float-value-slot
                other-pointer-lowtag)))
index fdf8ad7..ae0f2b8 100644 (file)
         (emit-mod-reg-r/m-byte segment #b11 reg (reg-tn-encoding thing)))
        (stack
         ;; Convert stack tns into an index off RBP.
-        (let ((disp (- (* (1+ (tn-offset thing)) n-word-bytes))))
+        (let ((disp (frame-byte-offset (tn-offset thing))))
           (cond ((<= -128 disp 127)
                  (emit-mod-reg-r/m-byte segment #b01 reg #b101)
                  (emit-byte segment disp))
index 4f37f5a..cd6642b 100644 (file)
                ;; Lisp stack
                (etypecase val
                  (integer
-                  (storew (fixnumize val) fp (- (1+ (tn-offset y)))))
+                  (storew (fixnumize val) fp (frame-word-offset (tn-offset y))))
                  (symbol
                   (storew (+ nil-value (static-symbol-offset val))
-                          fp (- (1+ (tn-offset y)))))
+                          fp (frame-word-offset (tn-offset y))))
                  (character
                   (storew (logior (ash (char-code val) n-widetag-bits)
                                   character-widetag)
-                          fp (- (1+ (tn-offset y))))))))
+                          fp (frame-word-offset (tn-offset y)))))))
          (if (= (tn-offset fp) esp-offset)
              ;; C-call
              (storew x fp (tn-offset y))
            ;; Lisp stack
-           (storew x fp (- (1+ (tn-offset y))))))))))
+           (storew x fp (frame-word-offset (tn-offset y)))))))))
 
 (define-move-vop move-arg :move-arg
   (any-reg descriptor-reg)
       ((signed-stack unsigned-stack)
        (if (= (tn-offset fp) esp-offset)
            (storew x fp (tn-offset y))  ; c-call
-           (storew x fp (- (1+ (tn-offset y)))))))))
+           (storew x fp (frame-word-offset (tn-offset y))))))))
 (define-move-vop move-word-arg :move-arg
   (descriptor-reg any-reg signed-reg unsigned-reg) (signed-reg unsigned-reg))
 
index dd31d2a..4cc02fd 100644 (file)
@@ -24,7 +24,7 @@
 (defun catch-block-ea (tn)
   (aver (sc-is tn catch-block))
   (make-ea :qword :base rbp-tn
-           :disp (- (* (+ (tn-offset tn) catch-block-size) n-word-bytes))))
+           :disp (frame-byte-offset (+ -1 (tn-offset tn) catch-block-size))))
 
 \f
 ;;;; Save and restore dynamic environment.
                    (storew rdx-tn rbx-tn -1))
                  (sc-case tn
                    ((descriptor-reg any-reg)
-                    (loadw tn start (frame-word-offset i)))
+                    (loadw tn start (frame-word-offset (+ sp->fp-offset i))))
                    ((control-stack)
-                    (loadw move-temp start (frame-word-offset i))
+                    (loadw move-temp start
+                           (frame-word-offset (+ sp->fp-offset i)))
                     (inst mov tn move-temp)))))
              (let ((defaulting-done (gen-label)))
                (emit-label defaulting-done)
 
     ;; Clear the stack
     (inst lea rsp-tn
-          (make-ea :qword :base rbp-tn :disp (* -3 n-word-bytes)))
+          (make-ea :qword :base rbp-tn
+                   :disp (* (- sp->fp-offset 3) n-word-bytes)))
 
     ;; Push the return-pc so it looks like we just called.
     (pushw rbp-tn (frame-word-offset return-pc-save-offset))
index 9177094..02aba44 100644 (file)
@@ -65,7 +65,7 @@
       (sap-stack
        (if (= (tn-offset fp) esp-offset)
            (storew x fp (tn-offset y))  ; c-call
-           (storew x fp (- (1+ (tn-offset y)))))))))
+           (storew x fp (frame-word-offset (tn-offset y))))))))
 (define-move-vop move-sap-arg :move-arg
   (descriptor-reg sap-reg) (sap-reg))
 
index ee2baea..e0b76ca 100644 (file)
@@ -16,9 +16,6 @@
   (:policy :safe)
   (:variant-vars function)
   (:vop-var vop)
-  ;;(:node-var node)
-  (:temporary (:sc unsigned-reg :offset ebx-offset
-                   :from (:eval 0) :to (:eval 2)) ebx)
   (:temporary (:sc unsigned-reg :offset ecx-offset
                    :from (:eval 0) :to (:eval 2)) ecx))
 
@@ -41,7 +38,8 @@
                (<= num-results register-arg-count))
     (error "either too many args (~W) or too many results (~W); max = ~W"
            num-args num-results register-arg-count))
-  (let ((num-temps (max num-args num-results)))
+  (let ((num-temps (max num-args num-results))
+        (node (gensym "NODE-")))
     (collect ((temp-names) (temps) (arg-names) (args) (result-names) (results))
       (dotimes (i num-results)
         (let ((result-name (intern (format nil "RESULT-~D" i))))
         ,@(temps)
         (:temporary (:sc unsigned-reg) call-target)
         (:results ,@(results))
+        (:node-var ,node)
         (:generator ,(+ 50 num-args num-results)
          ,@(moves (temp-names) (arg-names))
 
-         ;; If speed not more important than size, duplicate the
+         ;; If speed is at least as important as size, duplicate the
          ;; effect of the ENTER with discrete instructions. Takes
-         ;; 2+1+3+2=8 bytes as opposed to 4+3=7 bytes.
-         (cond (t ;(policy node (>= speed space))
-                (inst mov ebx rsp-tn)
-                ;; Dummy for return address
+         ;; 3+4+4=11 bytes as opposed to 1+4=5 bytes.
+         (cond ((policy ,node (>= speed space))
+                (inst sub rsp-tn (fixnumize 3))
+                (inst mov (make-ea :qword :base rsp-tn
+                                   :disp (frame-byte-offset
+                                          (+ sp->fp-offset
+                                             -3
+                                             ocfp-save-offset)))
+                      rbp-tn)
+                (inst lea rbp-tn (make-ea :qword :base rsp-tn
+                                          :disp (frame-byte-offset
+                                                 (+ sp->fp-offset
+                                                    -3
+                                                    ocfp-save-offset)))))
+               (t
+                ;; Dummy for return address.
                 (inst push rbp-tn)
-                ;; Save the old-fp
-                (inst push rbp-tn)
-                ;; Ensure that at least three slots are available; one
-                ;; above, two more needed.
-                (inst sub rsp-tn (fixnumize 1))
-                (inst mov rbp-tn ebx))
-               #+(or) (t
-                (inst enter (fixnumize 2))
-                ;; The enter instruction pushes EBP and then copies
-                ;; ESP into EBP. We want the new EBP to be the
-                ;; original ESP, so we fix it up afterwards.
-                (inst add rbp-tn (fixnumize 1))))
+                (inst enter (fixnumize 1))))
 
          ,(if (zerop num-args)
               '(inst xor ecx ecx)
index 491444e..1298a5e 100644 (file)
@@ -20,7 +20,7 @@
                (make-byte-tn value))
               ((sc-is value control-stack)
                (make-ea :byte :base rbp-tn
-                        :disp (- (* (1+ (tn-offset value)) n-word-bytes))))
+                        :disp (frame-byte-offset (tn-offset value))))
               (t
                value))
         sb!vm::fixnum-tag-mask))
index 405ca67..c946adb 100644 (file)
 \f
 ;;;; miscellaneous function call parameters
 
-;;; offsets of special stack frame locations
-(def!constant ocfp-save-offset 1)
+;;; Offsets of special stack frame locations relative to RBP.
+;;;
+;;; Consider the standard prologue PUSH RBP; MOV RBP, RSP: the return
+;;; address is at RBP+8, the old control stack frame pointer is at
+;;; RBP, the magic 3rd slot is at RBP-8. Then come the locals from
+;;; RBP-16 on.
 (def!constant return-pc-save-offset 0)
+(def!constant ocfp-save-offset 1)
 (def!constant code-save-offset 2)
+;;; Let SP be the stack pointer before CALLing, and FP is the frame
+;;; pointer after the standard prologue. SP +
+;;; FRAME-WORD-OFFSET(SP->FP-OFFSET + I) = FP + FRAME-WORD-OFFSET(I).
+(def!constant sp->fp-offset 2)
 
 (declaim (inline frame-word-offset))
 (defun frame-word-offset (index)
-  (- (1+ index)))
+  (- (1- index)))
 
 (declaim (inline frame-byte-offset))
 (defun frame-byte-offset (index)
index 7fcbed2..4d54c91 100644 (file)
       (inst lea esp-tn
             (make-ea :dword :base ebp-tn
                      :disp (- (* n-word-bytes
-                                 (max 3 (sb-allocated-size 'stack)))))))
+                                 (- (max 3 (sb-allocated-size 'stack))
+                                    sp->fp-offset))))))
 
     (trace-table-entry trace-table-normal)))
 
 ;;; or a multiple-call-local. All it does is allocate stack space for the
 ;;; callee (who has the same size stack as us).
 (define-vop (allocate-frame)
-  (:results (res :scs (any-reg control-stack))
+  (:results (res :scs (any-reg))
             (nfp))
   (:info callee)
   (:ignore nfp callee)
   (:generator 2
-    (move res esp-tn)
+    (inst lea res (make-ea :dword :base esp-tn
+                           :disp (- (* sp->fp-offset n-word-bytes))))
     (inst sub esp-tn (* n-word-bytes (sb-allocated-size 'stack)))))
 
 ;;; Allocate a partial frame for passing stack arguments in a full
 ;;; before it can extend the stack.
 (define-vop (allocate-full-call-frame)
   (:info nargs)
-  (:results (res :scs (any-reg control-stack)))
+  (:results (res :scs (any-reg)))
   (:generator 2
-    (move res esp-tn)
+    (inst lea res (make-ea :dword :base esp-tn
+                           :disp (- (* sp->fp-offset n-word-bytes))))
     (inst sub esp-tn (* (max nargs 3) n-word-bytes))))
 \f
 ;;; Emit code needed at the return-point from an unknown-values call
             (when first-stack-arg-p
               ;; There are stack args so the frame of the callee is
               ;; still there, save EDX in its first slot temporalily.
-              (storew edx-tn ebx-tn -1))
-            (loadw edx-tn ebx-tn (frame-word-offset i))
+              (storew edx-tn ebx-tn (frame-word-offset sp->fp-offset)))
+            (loadw edx-tn ebx-tn (frame-word-offset (+ sp->fp-offset i)))
             (inst mov tn edx-tn)))
 
         (emit-label defaulting-done)
-        (loadw edx-tn ebx-tn -1)
+        (loadw edx-tn ebx-tn (frame-word-offset sp->fp-offset))
         (move esp-tn ebx-tn)
 
         (let ((defaults (defaults)))
       ;; and then default the remaining stack arguments.
       (emit-label regs-defaulted)
       ;; Save EDI.
-      (storew edi-tn ebx-tn (frame-word-offset 1))
+      (storew edi-tn ebx-tn (frame-word-offset (+ sp->fp-offset 1)))
       ;; Compute the number of stack arguments, and if it's zero or
       ;; less, don't copy any stack arguments.
       (inst sub ecx-tn (fixnumize register-arg-count))
             (make-ea :dword :base ebp-tn
                      :disp (frame-byte-offset register-arg-count)))
       ;; Save ESI, and compute a pointer to where the args come from.
-      (storew esi-tn ebx-tn (frame-word-offset 2))
+      (storew esi-tn ebx-tn (frame-word-offset (+ sp->fp-offset 2)))
       (inst lea esi-tn
             (make-ea :dword :base ebx-tn
-                     :disp (frame-byte-offset register-arg-count)))
+                     :disp (frame-byte-offset
+                            (+ sp->fp-offset register-arg-count))))
       ;; Do the copy.
       (inst shr ecx-tn word-shift)              ; make word count
       (inst std)
       (inst rep)
       (inst movs :dword)
       ;; Restore ESI.
-      (loadw esi-tn ebx-tn (frame-word-offset 2))
+      (loadw esi-tn ebx-tn (frame-word-offset (+ sp->fp-offset 2)))
       ;; Now we have to default the remaining args. Find out how many.
       (inst sub eax-tn (fixnumize (- nvals register-arg-count)))
       (inst neg eax-tn)
       (inst stos eax-tn)
       ;; Restore EDI, and reset the stack.
       (emit-label restore-edi)
-      (loadw edi-tn ebx-tn (frame-word-offset 1))
+      (loadw edi-tn ebx-tn (frame-word-offset (+ sp->fp-offset 1)))
       (inst mov esp-tn ebx-tn)
       (inst cld))))
   (values))
     (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
     ;; Zot all of the stack except for the old-fp and return-pc.
-    (inst lea esp-tn
-          (make-ea :dword :base ebp-tn
-                   :disp (frame-byte-offset ocfp-save-offset)))
+    (inst mov esp-tn ebp-tn)
     (inst pop ebp-tn)
     (inst ret)
     (trace-table-entry trace-table-normal)))
                           ,(if variable
                                '(inst sub esp-tn (fixnumize 3)))
 
+                          ;; Bias the new-fp for use as an fp
+                          ,(if variable
+                               '(inst sub new-fp (fixnumize sp->fp-offset)))
+
                           ;; Save the fp
                           (storew ebp-tn new-fp
                                   (frame-word-offset ocfp-save-offset))
     (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
     ;; Drop stack above old-fp
-    (inst lea esp-tn (make-ea :dword :base ebp-tn
-                              :disp (frame-byte-offset (tn-offset old-fp))))
+    (inst mov esp-tn ebp-tn)
     ;; Clear the multiple-value return flag
     (inst clc)
     ;; Restore the old frame pointer
       (error "nvalues is 1"))
     (trace-table-entry trace-table-fun-epilogue)
     ;; Establish the values pointer and values count.
-    (move ebx ebp-tn)
+    (inst lea ebx (make-ea :dword :base ebp-tn
+                           :disp (* sp->fp-offset n-word-bytes)))
     (if (zerop nvals)
         (inst xor ecx ecx)              ; smaller
         (inst mov ecx (fixnumize nvals)))
-    ;; Clear as much of the stack as possible, but not past the old
-    ;; frame address.
-    (inst lea esp-tn
-          (make-ea :dword :base ebx
-                   :disp (frame-byte-offset
-                          (if (< register-arg-count nvals)
-                              (1- nvals)
-                              ocfp-save-offset))))
     ;; Pre-default any argument register that need it.
     (when (< nvals register-arg-count)
       (let* ((arg-tns (nthcdr nvals (list a0 a1 a2)))
     ;; stack and we've changed the stack pointer. So we have to
     ;; tell it to index off of EBX instead of EBP.
     (cond ((<= nvals register-arg-count)
+           (inst mov esp-tn ebp-tn)
            (inst pop ebp-tn)
            (inst ret))
           (t
            ;; Some values are on the stack after RETURN-PC and OLD-FP,
            ;; can't return normally and some slots of the frame will
            ;; be used as temporaries by the receiver.
+           ;;
+           ;; Clear as much of the stack as possible, but not past the
+           ;; old frame address.
+           (inst lea esp-tn
+                 (make-ea :dword :base ebp-tn
+                          :disp (frame-byte-offset (1- nvals))))
            (move ebp-tn old-fp)
            (inst push (make-ea :dword :base ebx
-                               :disp (frame-byte-offset (tn-offset return-pc))))
+                               :disp (frame-byte-offset
+                                      (+ sp->fp-offset
+                                         (tn-offset return-pc)))))
            (inst ret)))
 
     (trace-table-entry trace-table-normal)))
 ;;; assembly-routine.
 ;;;
 ;;; The assembly routine takes the following args:
-;;;  EAX -- the return-pc to finally jump to.
-;;;  EBX -- pointer to where to put the values.
 ;;;  ECX -- number of values to find there.
 ;;;  ESI -- pointer to where to find the values.
 (define-vop (return-multiple)
         (inst jmp :ne not-single)
         ;; Return with one value.
         (loadw a0 vals -1)
-        (inst lea esp-tn (make-ea :dword :base ebp-tn
-                                  :disp (frame-byte-offset ocfp-save-offset)))
+        ;; Clear the stack until ocfp.
+        (inst mov esp-tn ebp-tn)
         ;; clear the multiple-value return flag
         (inst clc)
         ;; Out of here.
            (inst jmp :be JUST-ALLOC-FRAME)))
 
     ;; Allocate the space on the stack.
-    ;; stack = ebp - (max 3 frame-size) - (nargs - fixed)
+    ;; stack = ebp + sp->fp-offset - (max 3 frame-size) - (nargs - fixed)
     (inst lea ebx-tn
           (make-ea :dword :base ebp-tn
-                   :disp (- (fixnumize fixed)
-                            (* n-word-bytes
+                   :disp (* n-word-bytes
+                            (- (+ sp->fp-offset fixed)
                                (max 3 (sb-allocated-size 'stack))))))
     (inst sub ebx-tn ecx-tn)  ; Got the new stack in ebx
     (inst mov esp-tn ebx-tn)
     ;; now.
 
     ;; Initialize src to be end of args.
-    (inst mov esi-tn ebp-tn)
+    (inst lea esi-tn (make-ea :dword :base ebp-tn
+                              :disp (* sp->fp-offset n-word-bytes)))
     (inst sub esi-tn ebx-tn)
 
     ;; We need to copy from downwards up to avoid overwriting some of
 
     ;; Here: nargs>=1 && nargs>fixed
     (when (< fixed register-arg-count)
-          ;; Now we have to deposit any more args that showed up in
-          ;; registers.
-          (do ((i fixed))
-              ( nil )
-              ;; Store it relative to ebp
-              (inst mov (make-ea :dword :base ebp-tn
-                                 :disp (- (* n-word-bytes
-                                             (+ 1 (- i fixed)
-                                                (max 3 (sb-allocated-size 'stack))))))
-                    (nth i *register-arg-tns*))
-
-              (incf i)
-              (when (>= i register-arg-count)
-                    (return))
-
-              ;; Don't deposit any more than there are.
-              (if (zerop i)
-                  (inst test ecx-tn ecx-tn)
-                (inst cmp ecx-tn (fixnumize i)))
-              (inst jmp :eq DONE)))
+      ;; Now we have to deposit any more args that showed up in
+      ;; registers.
+      (do ((i fixed))
+          ( nil )
+        ;; Store it relative to ebp
+        (inst mov (make-ea :dword :base ebp-tn
+                           :disp (* n-word-bytes
+                                    (- sp->fp-offset
+                                       (+ 1
+                                          (- i fixed)
+                                          (max 3 (sb-allocated-size
+                                                  'stack))))))
+              (nth i *register-arg-tns*))
+
+        (incf i)
+        (when (>= i register-arg-count)
+          (return))
+
+        ;; Don't deposit any more than there are.
+        (if (zerop i)
+            (inst test ecx-tn ecx-tn)
+            (inst cmp ecx-tn (fixnumize i)))
+        (inst jmp :eq DONE)))
 
     (inst jmp DONE)
 
     JUST-ALLOC-FRAME
     (inst lea esp-tn
           (make-ea :dword :base ebp-tn
-                   :disp (- (* n-word-bytes
+                   :disp (* n-word-bytes
+                            (- sp->fp-offset
                                (max 3 (sb-allocated-size 'stack))))))
 
     DONE))
index 5bb80e1..823ee8f 100644 (file)
@@ -71,7 +71,8 @@
     (move temp offset)
     (inst neg temp)
     (inst mov
-          (make-ea :dword :base sap :disp (frame-byte-offset 0) :index temp) value)
+          (make-ea :dword :base sap :disp (frame-byte-offset 0) :index temp)
+          value)
     (move result value)))
 
 (define-vop (write-control-stack-c)
@@ -84,8 +85,7 @@
   (:results (result :scs (descriptor-reg)))
   (:result-types *)
   (:generator 5
-    (inst mov (make-ea :dword :base sap
-                       :disp (frame-byte-offset index))
+    (inst mov (make-ea :dword :base sap :disp (frame-byte-offset index))
           value)
     (move result value)))
 
index 07d4032..96d2ca4 100644 (file)
                    (storew edx-tn ebx-tn -1))
                  (sc-case tn
                    ((descriptor-reg any-reg)
-                    (loadw tn start (frame-word-offset i)))
+                    (loadw tn start (frame-word-offset (+ sp->fp-offset i))))
                    ((control-stack)
-                    (loadw move-temp start (frame-word-offset i))
+                    (loadw move-temp start
+                           (frame-word-offset (+ sp->fp-offset i)))
                     (inst mov tn move-temp)))))
              (let ((defaulting-done (gen-label)))
                (emit-label defaulting-done)
 
     ;; Clear the stack
     (inst lea esp-tn
-          (make-ea :dword :base ebp-tn :disp (* -3 n-word-bytes)))
+          (make-ea :dword :base ebp-tn
+                   :disp (* (- sp->fp-offset 3) n-word-bytes)))
 
     ;; Push the return-pc so it looks like we just called.
     (pushw ebp-tn (frame-word-offset return-pc-save-offset))
index 675d204..6b9f03c 100644 (file)
@@ -16,9 +16,6 @@
   (:policy :safe)
   (:variant-vars function)
   (:vop-var vop)
-  ;;(:node-var node)
-  (:temporary (:sc unsigned-reg :offset ebx-offset
-                   :from (:eval 0) :to (:eval 2)) ebx)
   (:temporary (:sc unsigned-reg :offset ecx-offset
                    :from (:eval 0) :to (:eval 2)) ecx))
 
@@ -41,7 +38,8 @@
                (<= num-results register-arg-count))
     (error "either too many args (~W) or too many results (~W); max = ~W"
            num-args num-results register-arg-count))
-  (let ((num-temps (max num-args num-results)))
+  (let ((num-temps (max num-args num-results))
+        (node (gensym "NODE-")))
     (collect ((temp-names) (temps) (arg-names) (args) (result-names) (results))
       (dotimes (i num-results)
         (let ((result-name (intern (format nil "RESULT-~D" i))))
         (:args ,@(args))
         ,@(temps)
         (:results ,@(results))
+        (:node-var ,node)
         (:generator ,(+ 50 num-args num-results)
          ,@(moves (temp-names) (arg-names))
 
-         ;; If speed not more important than size, duplicate the
+         ;; If speed is at least as important as size, duplicate the
          ;; effect of the ENTER with discrete instructions. Takes
-         ;; 2+1+3+2=8 bytes as opposed to 4+3=7 bytes.
-         (cond (t ;(policy node (>= speed space))
-                (inst mov ebx esp-tn)
-                ;; Dummy for return address
+         ;; 3+4+4=11 bytes as opposed to 1+4=5 bytes.
+         (cond ((policy ,node (>= speed space))
+                (inst sub esp-tn (fixnumize 3))
+                (inst mov (make-ea :dword :base esp-tn
+                                   :disp (frame-byte-offset
+                                          (+ sp->fp-offset
+                                             -3
+                                             ocfp-save-offset)))
+                      ebp-tn)
+                (inst lea ebp-tn (make-ea :dword :base esp-tn
+                                          :disp (frame-byte-offset
+                                                 (+ sp->fp-offset
+                                                    -3
+                                                    ocfp-save-offset)))))
+               (t
+                ;; Dummy for return address.
                 (inst push ebp-tn)
-                ;; Save the old-fp
-                (inst push ebp-tn)
-                ;; Ensure that at least three slots are available; one
-                ;; above, two more needed.
-                (inst sub esp-tn (fixnumize 1))
-                (inst mov ebp-tn ebx))
-               #+(or) (t
-                (inst enter (fixnumize 2))
-                ;; The enter instruction pushes EBP and then copies
-                ;; ESP into EBP. We want the new EBP to be the
-                ;; original ESP, so we fix it up afterwards.
-                (inst add ebp-tn (fixnumize 1))))
+                (inst enter (fixnumize 1))))
 
          ,(if (zerop num-args)
               '(inst xor ecx ecx)
index 7b1f486..5313dc3 100644 (file)
 \f
 ;;;; miscellaneous function call parameters
 
-;;; offsets of special stack frame locations
-(def!constant ocfp-save-offset 1)
+;;; Offsets of special stack frame locations relative to EBP.
+;;;
+;;; Consider the standard prologue PUSH EBP; MOV EBP, ESP: the return
+;;; address is at EBP+4, the old control stack frame pointer is at
+;;; EBP, the magic 3rd slot is at EBP-4. Then come the locals from
+;;; EBP-8 on.
 (def!constant return-pc-save-offset 0)
+(def!constant ocfp-save-offset 1)
+;;; Let SP be the stack pointer before CALLing, and FP is the frame
+;;; pointer after the standard prologue. SP +
+;;; FRAME-WORD-OFFSET(SP->FP-OFFSET + I) = FP + FRAME-WORD-OFFSET(I).
+(def!constant sp->fp-offset 2)
 
 (declaim (inline frame-word-offset))
 (defun frame-word-offset (index)
-  (- (1+ index)))
+  (- (1- index)))
 
 (declaim (inline frame-byte-offset))
 (defun frame-byte-offset (index)
index ea53069..348d204 100644 (file)
@@ -324,55 +324,21 @@ ra_pointer_p (void *ra)
 static int
 x86_call_context (void *fp, void **ra, void **ocfp)
 {
-  void *lisp_ocfp;
-  void *lisp_ra;
   void *c_ocfp;
   void *c_ra;
-  int lisp_valid_p, c_valid_p;
+  int c_valid_p;
 
   if (!stack_pointer_p(fp))
     return 0;
 
   c_ocfp    = *((void **) fp);
   c_ra      = *((void **) fp + 1);
-  lisp_ocfp = *((void **) fp - 2);
-  lisp_ra   = *((void **) fp - 1);
 
-  lisp_valid_p = (lisp_ocfp > fp
-                  && stack_pointer_p(lisp_ocfp)
-                  && ra_pointer_p(lisp_ra));
   c_valid_p = (c_ocfp > fp
                && stack_pointer_p(c_ocfp)
                && ra_pointer_p(c_ra));
 
-  if (lisp_valid_p && c_valid_p) {
-    void *lisp_path_fp;
-    void *c_path_fp;
-    void *dummy;
-
-    int lisp_path_p = x86_call_context(lisp_ocfp, &lisp_path_fp, &dummy);
-    int c_path_p = x86_call_context(c_ocfp, &c_path_fp, &dummy);
-
-    if (lisp_path_p && c_path_p) {
-#if defined __FreeBSD__ && __FreeBSD_version > 400000
-      if (lisp_ocfp > c_ocfp)
-        *ra = lisp_ra, *ocfp = lisp_ocfp;
-      else
-        *ra = c_ra, *ocfp = c_ocfp;
-#else
-      *ra = lisp_ra, *ocfp = lisp_ocfp;
-#endif
-    }
-    else if (lisp_path_p)
-      *ra = lisp_ra, *ocfp = lisp_ocfp;
-    else if (c_path_p)
-      *ra = c_ra, *ocfp = c_ocfp;
-    else
-      return 0;
-  }
-  else if (lisp_valid_p)
-    *ra = lisp_ra, *ocfp = lisp_ocfp;
-  else if (c_valid_p)
+  if (c_valid_p)
     *ra = c_ra, *ocfp = c_ocfp;
   else
     return 0;
index 64f04ee..79140e0 100644 (file)
@@ -209,11 +209,10 @@ Ldone:
        xor     %rbx,%rbx       # available
 
        /* Alloc new frame. */
-       mov     %rsp,%rbx       # The current sp marks start of new frame.
-       push    %rbp            # dummy for return address
-       push    %rbp            # fp in save location S0
+       push    %rbp            # Dummy for return address
+       push    %rbp            # fp in save location S1
+       mov     %rsp,%rbp       # The current sp marks start of new frame.
        sub     $8,%rsp         # Ensure 3 slots are allocated, two above.
-       mov     %rbx,%rbp       # Switch to new frame.
 
 Lcall:
        call    *CLOSURE_FUN_OFFSET(%rax)
index 04c6031..37fcafa 100644 (file)
@@ -272,11 +272,10 @@ Ldone:
 #endif
 
        /* Alloc new frame. */
-       mov     %esp,%ebx       # The current sp marks start of new frame.
-       push    %ebp            # dummy for return address
+       push    %ebp            # Dummy for return address
        push    %ebp            # fp in save location S1
+       mov     %esp,%ebp       # The current sp marks start of new frame.
        sub     $4,%esp         # Ensure 3 slots are allocated, two above.
-       mov     %ebx,%ebp       # Switch to new frame.
 
        call    *CLOSURE_FUN_OFFSET(%eax)
        
index c670ede..629910d 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.27.13"
+"1.0.27.14"