From f78e2d271f540d68d35b4f41696ce746ff129ee3 Mon Sep 17 00:00:00 2001 From: Christophe Rhodes Date: Sat, 4 Mar 2006 19:58:26 +0000 Subject: [PATCH] 0.9.10.11: Merge patch (Alastair Bridgewater 2006-02-06 / CSR 2006-03-03) implementing a better calling convention on the x86 (and probably a better one on the x86-64). ... increment fasl version, because mixing calling conventions is a spectacular no-no. ... take this opportunity to put :gencgc on *features-potentially-affecting...*, since mixing gencgc and cheney allocation strategies on the ppc is also a spectacular no-no. --- NEWS | 5 ++ src/assembly/x86-64/arith.lisp | 34 +++++--------- src/assembly/x86-64/assem-rtns.lisp | 6 ++- src/assembly/x86-64/support.lisp | 11 ++--- src/assembly/x86/arith.lisp | 37 ++++++--------- src/assembly/x86/assem-rtns.lisp | 6 ++- src/assembly/x86/support.lisp | 25 +++++++--- src/code/early-fasl.lisp | 6 ++- src/compiler/x86-64/call.lisp | 83 ++++++++++++++++++++++++--------- src/compiler/x86/call.lisp | 87 +++++++++++++++++++++++++++-------- src/runtime/x86-64-assem.S | 9 ++-- src/runtime/x86-assem.S | 4 +- version.lisp-expr | 2 +- 13 files changed, 205 insertions(+), 110 deletions(-) diff --git a/NEWS b/NEWS index 80242ed..5059228 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,11 @@ changes in sbcl-0.9.11 relative to sbcl-0.9.10: * optimization: calling functions via constant symbols -- as in (FUNCALL 'FOO) -- is now roughly as efficient as calling them via the function object as in (FUNCALL #'FOO). + * optimization: on x86 and x86-64, the calling convention for the + case of dealing with an unknown number of values has been altered + to be friendlier to the prediction heuristics implemented, + particularly with reference to CALL and RET pairing. (thanks to + Alastair Bridgewater) * enhancement: CONSTANTP is now able to determine constantness of more complex forms, including calls to constant-foldable standardized functions and some special forms beyond QUOTE. diff --git a/src/assembly/x86-64/arith.lisp b/src/assembly/x86-64/arith.lisp index ef19c4f..4e8f81d 100644 --- a/src/assembly/x86-64/arith.lisp +++ b/src/assembly/x86-64/arith.lisp @@ -197,23 +197,15 @@ INLINE-FIXNUM-COMPARE (inst cmp x y) - (inst jmp ,test RETURN-TRUE) (inst mov res nil-value) - ;; FIXME: A note explaining this return convention, or a - ;; symbolic name for it, would be nice. (It looks as though we - ;; should be hand-crafting the same return sequence as would be - ;; produced by GENERATE-RETURN-SEQUENCE, but in that case it's - ;; not clear why we don't just jump to the end of this function - ;; to share the return sequence there. - (inst pop eax) - (inst add eax 3) - (inst jmp eax) - + (inst jmp ,test RETURN-FALSE) RETURN-TRUE - (load-symbol res t)))) + (load-symbol res t) + RETURN-FALSE + DONE))) - (define-cond-assem-rtn generic-< < two-arg-< :l) - (define-cond-assem-rtn generic-> > two-arg-> :g)) + (define-cond-assem-rtn generic-< < two-arg-< :ge) + (define-cond-assem-rtn generic-> > two-arg-> :le)) (define-assembly-routine (generic-eql (:cost 10) @@ -237,9 +229,7 @@ RETURN-NIL (inst mov res nil-value) - (inst pop eax) - (inst add eax 3) - (inst jmp eax) + (inst jmp DONE) DO-STATIC-FN (inst pop eax) @@ -253,8 +243,7 @@ RETURN-T (load-symbol res t) - ;; FIXME: I don't understand how we return from here.. - ) + DONE) (define-assembly-routine (generic-= (:cost 10) @@ -278,9 +267,7 @@ (inst jmp :e RETURN-T) ; ok (inst mov res nil-value) - (inst pop eax) - (inst add eax 3) - (inst jmp eax) + (inst jmp DONE) DO-STATIC-FN (inst pop eax) @@ -293,6 +280,7 @@ :disp (+ nil-value (static-fun-offset 'two-arg-=)))) RETURN-T - (load-symbol res t)) + (load-symbol res t) + DONE) diff --git a/src/assembly/x86-64/assem-rtns.lisp b/src/assembly/x86-64/assem-rtns.lisp index bd70889..5289615 100644 --- a/src/assembly/x86-64/assem-rtns.lisp +++ b/src/assembly/x86-64/assem-rtns.lisp @@ -67,6 +67,7 @@ (loadw esi ebx -3) ;; And back we go. + (inst stc) (inst jmp eax) ;; Handle the register arg cases. @@ -75,13 +76,14 @@ (inst mov edx nil-value) (inst mov edi edx) (inst mov esi edx) + (inst stc) (inst jmp eax) ONE-VALUE ; Note: we can get this, because the return-multiple vop ; doesn't check for this case when size > speed. (loadw edx esi -1) (inst mov rsp-tn ebx) - (inst add eax 3) + (inst clc) (inst jmp eax) TWO-VALUES @@ -89,6 +91,7 @@ (loadw edi esi -2) (inst mov esi nil-value) (inst lea rsp-tn (make-ea :qword :base ebx :disp (* -2 n-word-bytes))) + (inst stc) (inst jmp eax) THREE-VALUES @@ -96,6 +99,7 @@ (loadw edi esi -2) (loadw esi esi -3) (inst lea rsp-tn (make-ea :qword :base ebx :disp (* -3 n-word-bytes))) + (inst stc) (inst jmp eax)) ;;;; TAIL-CALL-VARIABLE diff --git a/src/assembly/x86-64/support.lisp b/src/assembly/x86-64/support.lisp index 5e10c88..96f1ef3 100644 --- a/src/assembly/x86-64/support.lisp +++ b/src/assembly/x86-64/support.lisp @@ -24,7 +24,9 @@ (make-ea :qword :disp (make-fixup ',name :assembly-routine))) (inst call temp-reg-tn) (note-this-location ,vop :single-value-return) - (move rsp-tn rbx-tn)) + (inst jmp :nc single-value) + (move rsp-tn rbx-tn) + single-value) '((:save-p :compute-only)))) (:none (values @@ -38,9 +40,6 @@ (:raw `(inst ret)) (:full-call - `( - (inst pop rax-tn) - - (inst add rax-tn 3) - (inst jmp rax-tn))) + `((inst clc) + (inst ret))) (:none))) diff --git a/src/assembly/x86/arith.lisp b/src/assembly/x86/arith.lisp index 1365fba..46aa23c 100644 --- a/src/assembly/x86/arith.lisp +++ b/src/assembly/x86/arith.lisp @@ -197,23 +197,16 @@ INLINE-FIXNUM-COMPARE (inst cmp x y) - (inst jmp ,test RETURN-TRUE) (inst mov res nil-value) - ;; FIXME: A note explaining this return convention, or a - ;; symbolic name for it, would be nice. (It looks as though we - ;; should be hand-crafting the same return sequence as would be - ;; produced by GENERATE-RETURN-SEQUENCE, but in that case it's - ;; not clear why we don't just jump to the end of this function - ;; to share the return sequence there. - (inst pop eax) - (inst add eax 2) - (inst jmp eax) + (inst jmp ,test RETURN-FALSE) + + (load-symbol res t) - RETURN-TRUE - (load-symbol res t)))) + RETURN-FALSE + DONE))) - (define-cond-assem-rtn generic-< < two-arg-< :l) - (define-cond-assem-rtn generic-> > two-arg-> :g)) + (define-cond-assem-rtn generic-< < two-arg-< :ge) + (define-cond-assem-rtn generic-> > two-arg-> :le)) (define-assembly-routine (generic-eql (:cost 10) @@ -237,9 +230,7 @@ RETURN-NIL (inst mov res nil-value) - (inst pop eax) - (inst add eax 2) - (inst jmp eax) + (inst jmp DONE) DO-STATIC-FN (inst pop eax) @@ -253,8 +244,8 @@ RETURN-T (load-symbol res t) - ;; FIXME: I don't understand how we return from here.. - ) + + DONE) (define-assembly-routine (generic-= (:cost 10) @@ -278,9 +269,7 @@ (inst jmp :e RETURN-T) ; ok (inst mov res nil-value) - (inst pop eax) - (inst add eax 2) - (inst jmp eax) + (inst jmp DONE) DO-STATIC-FN (inst pop eax) @@ -293,7 +282,9 @@ :disp (+ nil-value (static-fun-offset 'two-arg-=)))) RETURN-T - (load-symbol res t)) + (load-symbol res t) + + DONE) ;;; Support for the Mersenne Twister, MT19937, random number generator diff --git a/src/assembly/x86/assem-rtns.lisp b/src/assembly/x86/assem-rtns.lisp index 5d7d029..07f017f 100644 --- a/src/assembly/x86/assem-rtns.lisp +++ b/src/assembly/x86/assem-rtns.lisp @@ -70,6 +70,7 @@ (loadw esi ebx -3) ;; And back we go. + (inst stc) (inst jmp eax) ;; Handle the register arg cases. @@ -78,13 +79,14 @@ (inst mov edx nil-value) (inst mov edi edx) (inst mov esi edx) + (inst stc) (inst jmp eax) ONE-VALUE ; Note: we can get this, because the return-multiple vop ; doesn't check for this case when size > speed. (loadw edx esi -1) (inst mov esp-tn ebx) - (inst add eax 2) + (inst clc) (inst jmp eax) TWO-VALUES @@ -92,6 +94,7 @@ (loadw edi esi -2) (inst mov esi nil-value) (inst lea esp-tn (make-ea :dword :base ebx :disp (* -2 n-word-bytes))) + (inst stc) (inst jmp eax) THREE-VALUES @@ -99,6 +102,7 @@ (loadw edi esi -2) (loadw esi esi -3) (inst lea esp-tn (make-ea :dword :base ebx :disp (* -3 n-word-bytes))) + (inst stc) (inst jmp eax)) ;;;; TAIL-CALL-VARIABLE diff --git a/src/assembly/x86/support.lisp b/src/assembly/x86/support.lisp index 1e51079..527e326 100644 --- a/src/assembly/x86/support.lisp +++ b/src/assembly/x86/support.lisp @@ -9,6 +9,20 @@ (in-package "SB!VM") +;;; The :full-call assembly-routines must use the same full-call +;;; unknown-values return convention as a normal call, as some +;;; of the routines will tail-chain to a static-function. The +;;; routines themselves, however, take all of their arguments +;;; in registers (this will typically be one or two arguments, +;;; and is one of the lower bounds on the number of argument- +;;; passing registers), and thus don't need a call frame, which +;;; simplifies things for the normal call/return case. When it +;;; is neccessary for one of the assembly-functions to call a +;;; static-function it will construct the required call frame. +;;; Also, none of the assembly-routines return other than one +;;; value, which again simplifies the return path. +;;; -- AB, 2006/Feb/05. + (!def-vm-support-routine generate-call-sequence (name style vop) (ecase style ((:raw :none) @@ -20,7 +34,9 @@ `((note-this-location ,vop :call-site) (inst call (make-fixup ',name :assembly-routine)) (note-this-location ,vop :single-value-return) - (move esp-tn ebx-tn)) + (inst jmp :nc single-value) + (move esp-tn ebx-tn) + single-value) '((:save-p :compute-only)))))) (!def-vm-support-routine generate-return-sequence (style) @@ -28,9 +44,6 @@ (:raw `(inst ret)) (:full-call - `( - (inst pop eax-tn) - - (inst add eax-tn 2) - (inst jmp eax-tn))) + `((inst clc) + (inst ret))) (:none))) diff --git a/src/code/early-fasl.lisp b/src/code/early-fasl.lisp index 73c3454..68eee80 100644 --- a/src/code/early-fasl.lisp +++ b/src/code/early-fasl.lisp @@ -35,7 +35,7 @@ (macrolet ((define-fasl-format-features () (let (;; master value for *F-P-A-F-F* - (fpaff '(:sb-thread :sb-package-locks :sb-unicode))) + (fpaff '(:sb-thread :sb-package-locks :sb-unicode :gencgc))) `(progn ;; a list of *(SHEBANG-)FEATURES* flags which affect ;; binary compatibility, i.e. which must be the same @@ -76,7 +76,7 @@ ;;; versions which break binary compatibility. But it certainly should ;;; be incremented for release versions which break binary ;;; compatibility. -(def!constant +fasl-file-version+ 63) +(def!constant +fasl-file-version+ 64) ;;; (record of versions before 2003 deleted in 2003-04-26/0.pre8.107 or so) ;;; 38: (2003-01-05) changed names of internal SORT machinery ;;; 39: (2003-02-20) in 0.7.12.1 a slot was added to @@ -132,6 +132,8 @@ ;;; a 32-bit value also on 64-bit platforms. ;;; 63: (2006-01-27) Shuffle storage classes around to reduce the error ;;; trap information size on RISCy platforms. +;;; 64: (2006-03-24) New calling convention for unknown-values on x86 and +;;; x86-64. Also (belatedly) PPC/gencgc, including :gencgc on FPAFF. ;;; the conventional file extension for our fasl files (declaim (type simple-string *fasl-file-type*)) diff --git a/src/compiler/x86-64/call.lisp b/src/compiler/x86-64/call.lisp index 384155b..1e98a64 100644 --- a/src/compiler/x86-64/call.lisp +++ b/src/compiler/x86-64/call.lisp @@ -200,12 +200,14 @@ (cond ((<= nvals 1) (note-this-location vop :single-value-return) - (inst mov rsp-tn rbx-tn)) + (let ((single-value (gen-label))) + (inst jmp :nc single-value) + (inst mov rsp-tn rbx-tn) + (emit-label single-value))) ((<= nvals register-arg-count) (let ((regs-defaulted (gen-label))) (note-this-location vop :unknown-return) - (inst nop) - (inst jmp-short regs-defaulted) + (inst jmp :c regs-defaulted) ;; Default the unsupplied registers. (let* ((2nd-tn-ref (tn-ref-across values)) (2nd-tn (tn-ref-tn 2nd-tn-ref))) @@ -229,8 +231,7 @@ (default-stack-slots (gen-label))) (note-this-location vop :unknown-return) ;; Branch off to the MV case. - (inst nop) - (inst jmp-short regs-defaulted) + (inst jmp :c regs-defaulted) ;; Do the single value case. ;; Default the register args (inst mov rax-tn nil-value) @@ -385,8 +386,7 @@ (declare (type tn args nargs start count)) (let ((variable-values (gen-label)) (done (gen-label))) - (inst nop) - (inst jmp-short variable-values) + (inst jmp :c variable-values) (cond ((location= start (first *register-arg-tns*)) (inst push (first *register-arg-tns*)) @@ -939,21 +939,60 @@ (:args (old-fp) (return-pc) (value)) - (:temporary (:sc unsigned-reg) ofp) - (:temporary (:sc unsigned-reg) ret) (:ignore value) (:generator 6 (trace-table-entry trace-table-fun-epilogue) - (move ret return-pc) - ;; Clear the control stack - (move ofp old-fp) - ;; Adjust the return address for the single value return. - (inst add ret 3) - ;; Restore the frame pointer. - (move rsp-tn rbp-tn) - (move rbp-tn ofp) - ;; Out of here. - (inst jmp ret))) + ;; Code structure lifted from known-return. + (sc-case return-pc + ((sap-reg) + ;; return PC in register for some reason (local call?) + ;; we jmp to the return pc after fixing the stack and frame. + (sc-case old-fp + ((control-stack) + ;; ofp on stack must be in slot 0 (the traditional storage place). + ;; Drop the stack above it and pop it off. + (cond ((zerop (tn-offset old-fp)) + (inst lea rsp-tn (make-ea :dword :base rbp-tn + :disp (- (* (1+ ocfp-save-offset) + n-word-bytes)))) + (inst pop rbp-tn)) + (t + ;; Should this ever happen, we do the same as above, but + ;; using (tn-offset old-fp) instead of ocfp-save-offset + ;; (which is 0 anyway, see src/compiler/x86/vm.lisp) and + ;; then lea rsp again against itself with a displacement + ;; of (* (tn-offset old-fp) n-word-bytes) to clear the + ;; rest of the stack. + (cerror "Continue anyway" + "VOP return-single doesn't work if old-fp (in slot ~S) is not in slot 0" (tn-offset old-fp))))) + ((any-reg descriptor-reg) + ;; ofp in reg, drop the stack and load the real fp. + (move rsp-tn rbp-tn) + (move rbp-tn old-fp))) + + ;; Set single-value-return flag + (inst clc) + ;; And return + (inst jmp return-pc)) + + ((sap-stack) + ;; Note that this will only work right if, when old-fp is on + ;; the stack, it has a lower tn-offset than return-pc. One of + ;; the comments in known-return indicate that this is the case + ;; (in that it will be in its save location), but we may wish + ;; to assert that (in either the weaker or stronger forms). + ;; Should this ever not be the case, we should load old-fp + ;; into a temp reg while we fix the stack. + ;; Drop stack above return-pc + (inst lea rsp-tn (make-ea :dword :base rbp-tn + :disp (- (* (1+ (tn-offset return-pc)) + n-word-bytes)))) + ;; Set single-value return flag + (inst clc) + ;; Restore the old frame pointer + (move rbp-tn old-fp) + ;; And return, dropping the rest of the stack as we go. + (inst ret (* (tn-offset return-pc) n-word-bytes)))))) ;;; Do unknown-values return of a fixed (other than 1) number of ;;; values. The VALUES are required to be set up in the standard @@ -1004,6 +1043,8 @@ (inst mov first nil-value) (dolist (tn (cdr arg-tns)) (inst mov tn first)))) + ;; Set the multiple value return flag. + (inst stc) ;; And away we go. Except that return-pc is still on the ;; stack and we've changed the stack pointer. So we have to ;; tell it to index off of RBX instead of RBP. @@ -1065,8 +1106,8 @@ (move old-fp-temp old-fp) (move rsp-tn rbp-tn) (move rbp-tn old-fp-temp) - ;; Fix the return-pc to point at the single-value entry point. - (inst add rax 3) ; skip "mov %rbx,%rsp" insn in caller + ;; clear the multiple-value return flag + (inst clc) ;; Out of here. (inst jmp rax) diff --git a/src/compiler/x86/call.lisp b/src/compiler/x86/call.lisp index d2ab004..c84fe9c 100644 --- a/src/compiler/x86/call.lisp +++ b/src/compiler/x86/call.lisp @@ -200,11 +200,14 @@ (cond ((<= nvals 1) (note-this-location vop :single-value-return) - (inst mov esp-tn ebx-tn)) + (let ((single-value (gen-label))) + (inst jmp :nc single-value) + (inst mov esp-tn ebx-tn) + (emit-label single-value))) ((<= nvals register-arg-count) (let ((regs-defaulted (gen-label))) (note-this-location vop :unknown-return) - (inst jmp-short regs-defaulted) + (inst jmp :c regs-defaulted) ;; Default the unsuppled registers. (let* ((2nd-tn-ref (tn-ref-across values)) (2nd-tn (tn-ref-tn 2nd-tn-ref))) @@ -228,7 +231,7 @@ (default-stack-slots (gen-label))) (note-this-location vop :unknown-return) ;; Branch off to the MV case. - (inst jmp-short regs-defaulted) + (inst jmp :c regs-defaulted) ;; Do the single value case. ;; Default the register args (inst mov eax-tn nil-value) @@ -286,7 +289,7 @@ (count-okay (gen-label))) (note-this-location vop :unknown-return) ;; Branch off to the MV case. - (inst jmp-short regs-defaulted) + (inst jmp :c regs-defaulted) ;; Default the register args, and set up the stack as if we ;; entered the MV return point. @@ -389,7 +392,7 @@ (declare (type tn args nargs start count)) (let ((variable-values (gen-label)) (done (gen-label))) - (inst jmp-short variable-values) + (inst jmp :c variable-values) (cond ((location= start (first *register-arg-tns*)) (inst push (first *register-arg-tns*)) @@ -955,25 +958,69 @@ ;;; ;;; pfw--get wired-tn conflicts sometimes if register sc specd for args ;;; having problems targeting args to regs -- using temps instead. +;;; +;;; First off, modifying the return-pc defeats the branch-prediction +;;; optimizations on modern CPUs quite handily. Second, we can do all +;;; this without needing a temp register. Fixed the latter, at least. +;;; -- AB 2006/Feb/04 (define-vop (return-single) (:args (old-fp) (return-pc) (value)) - (:temporary (:sc unsigned-reg) ofp) - (:temporary (:sc unsigned-reg) ret) (:ignore value) (:generator 6 (trace-table-entry trace-table-fun-epilogue) - (move ret return-pc) - ;; Clear the control stack - (move ofp old-fp) - ;; Adjust the return address for the single value return. - (inst add ret 2) - ;; Restore the frame pointer. - (move esp-tn ebp-tn) - (move ebp-tn ofp) - ;; Out of here. - (inst jmp ret))) + ;; Code structure lifted from known-return. + (sc-case return-pc + ((sap-reg) + ;; return PC in register for some reason (local call?) + ;; we jmp to the return pc after fixing the stack and frame. + (sc-case old-fp + ((control-stack) + ;; ofp on stack must be in slot 0 (the traditional storage place). + ;; Drop the stack above it and pop it off. + (cond ((zerop (tn-offset old-fp)) + (inst lea esp-tn (make-ea :dword :base ebp-tn + :disp (- (* (1+ ocfp-save-offset) + n-word-bytes)))) + (inst pop ebp-tn)) + (t + ;; Should this ever happen, we do the same as above, but + ;; using (tn-offset old-fp) instead of ocfp-save-offset + ;; (which is 0 anyway, see src/compiler/x86/vm.lisp) and + ;; then lea esp again against itself with a displacement + ;; of (* (tn-offset old-fp) n-word-bytes) to clear the + ;; rest of the stack. + (cerror "Continue anyway" + "VOP return-single doesn't work if old-fp (in slot ~S) is not in slot 0" (tn-offset old-fp))))) + ((any-reg descriptor-reg) + ;; ofp in reg, drop the stack and load the real fp. + (move esp-tn ebp-tn) + (move ebp-tn old-fp))) + + ;; Set single-value-return flag + (inst clc) + ;; And return + (inst jmp return-pc)) + + ((sap-stack) + ;; Note that this will only work right if, when old-fp is on + ;; the stack, it has a lower tn-offset than return-pc. One of + ;; the comments in known-return indicate that this is the case + ;; (in that it will be in its save location), but we may wish + ;; to assert that (in either the weaker or stronger forms). + ;; Should this ever not be the case, we should load old-fp + ;; into a temp reg while we fix the stack. + ;; Drop stack above return-pc + (inst lea esp-tn (make-ea :dword :base ebp-tn + :disp (- (* (1+ (tn-offset return-pc)) + n-word-bytes)))) + ;; Set single-value return flag + (inst clc) + ;; Restore the old frame pointer + (move ebp-tn old-fp) + ;; And return, dropping the rest of the stack as we go. + (inst ret (* (tn-offset return-pc) n-word-bytes)))))) ;;; Do unknown-values return of a fixed (other than 1) number of ;;; values. The VALUES are required to be set up in the standard @@ -1024,6 +1071,8 @@ (inst mov first nil-value) (dolist (tn (cdr arg-tns)) (inst mov tn first)))) + ;; Set multi-value return flag. + (inst stc) ;; And away we go. Except that return-pc is still on the ;; stack and we've changed the stack pointer. So we have to ;; tell it to index off of EBX instead of EBP. @@ -1084,8 +1133,8 @@ (move old-fp-temp old-fp) (move esp-tn ebp-tn) (move ebp-tn old-fp-temp) - ;; Fix the return-pc to point at the single-value entry point. - (inst add eax 2) + ;; Set the single-value return flag. + (inst clc) ;; Out of here. (inst jmp eax) diff --git a/src/runtime/x86-64-assem.S b/src/runtime/x86-64-assem.S index 02c508a..92e0716 100644 --- a/src/runtime/x86-64-assem.S +++ b/src/runtime/x86-64-assem.S @@ -170,8 +170,9 @@ Lcall: /* If the function returned multiple values, it will return to this point. Lose them */ + jnc LsingleValue mov %rbx, %rsp - /* A singled value function returns here */ +LsingleValue: /* Restore the stack, in case there was a stack change. */ pop %rsp # c-sp @@ -290,11 +291,7 @@ GNAME(closure_tramp): .align align_8byte GNAME(fun_end_breakpoint_guts): /* Multiple Value return */ - jmp multiple_value_return - /* the above jmp is only 2 bytes long, we need to add a nop for - * padding since the single value return convention jumps to original - * return address + 3 bytes */ - nop + jc multiple_value_return /* Single value return: The eventual return will now use the multiple values return convention but with a return values count of one. */ diff --git a/src/runtime/x86-assem.S b/src/runtime/x86-assem.S index 2069f96..e3b36c7 100644 --- a/src/runtime/x86-assem.S +++ b/src/runtime/x86-assem.S @@ -264,7 +264,9 @@ Ldone: /* If the function returned multiple values, it will return to this point. Lose them */ + jnc LsingleValue mov %ebx, %esp +LsingleValue: /* A singled value function returns here */ /* Restore the stack, in case there was a stack change. */ @@ -348,7 +350,7 @@ GNAME(closure_tramp): .align align_4byte GNAME(fun_end_breakpoint_guts): /* Multiple Value return */ - jmp multiple_value_return + jc multiple_value_return /* Single value return: The eventual return will now use the multiple values return convention but with a return values count of one. */ diff --git a/version.lisp-expr b/version.lisp-expr index 29ff189..d8904c2 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -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".) -"0.9.10.10" +"0.9.10.11" -- 1.7.10.4