From: Nathan F. <fr...@cs...> - 2006-10-26 13:52:03
|
On Thu, Oct 26, 2006 at 12:01:08AM -0500, Brian Downing wrote: > On Wed, Oct 25, 2006 at 02:24:20PM -0500, Nathan Froyd wrote: > > I am guessing from your prompts that you are using slime. Functions > > compiled at the slime toplevel have an extra (lambda () ...) wrapped > > around them and I believe this accounts for the extra code that you > > see. This is also the reason, btw, that there are *two* > > INVALID-ARG-COUNT-ERRORs in your first disassembly and only one is > > reachable. > > I don't believe this is the case. The extra lambda going to > ACTUALLY-COMPILE in this case comes from %simple-eval: You're right; I had seen this behavior before, but for some reason attributed it to slime. > ;;; general case of EVAL (except in that it can't handle toplevel > ;;; EVAL-WHEN magic properly): Delegate to #'COMPILE. > (defun %simple-eval (expr lexenv) > ;; FIXME: It might be nice to quieten the toplevel by muffling > ;; warnings generated by this compilation (since we're about to > ;; execute the results irrespective of the warnings). We might want > ;; to be careful about not muffling warnings arising from inner > ;; evaluations/compilations, though [e.g. the ignored variable in > ;; (DEFUN FOO (X) 1)]. -- CSR, 2003-05-13 > (let ((fun (sb!c:compile-in-lexenv nil > `(lambda () ,expr) > lexenv))) > (funcall fun))) If this is the problem, why not do: (defun %simple-eval (expr lexenv) ;; FIXME: It might be nice to quieten the toplevel by muffling ;; warnings generated by this compilation (since we're about to ;; execute the results irrespective of the warnings). We might want ;; to be careful about not muffling warnings arising from inner ;; evaluations/compilations, though [e.g. the ignored variable in ;; (DEFUN FOO (X) 1)]. -- CSR, 2003-05-13 (cond ((eq (car expr) 'sb-int:named-lambda) (sb!c:compile-in-lexenv nil expr lexenv)) (t (let ((fun (sb!c:compile-in-lexenv nil `(lambda () ,expr) lexenv))) (funcall fun))))) > Here is a session with raw SBCL. Note that the disassemble-code-component > output is royally horked on AMD64 - for some reason the segment start > address is before the actual address of the instruction. This was also > the case in your version: I don't think it's so much horked as SBCL just isn't doing what might be expected. Code components can have multiple entry points, which is what disassemble-code-component is telling you. It just so happens that the entry point you care about is located in the middle of the code component. You can poke at something like: (labels ((cmpx (x y) (declare (type double-float x y)) (not (cmp3 x y))) (cmpy (x y) (declare (type double-float x y)) (cmp3 x y)) (cmp3 (x y) (declare (type double-float x y)) (< x y))) (setf (fdefinition 'cmp) #'cmpx) (setf (fdefinition 'cmp2) #'cmpy)) (sb-disassem::fun-code (symbol-function 'cmp)) (sb-disassem::fun-code (symbol-function 'cmp2)) to see for yourself. (This also supports block compilation in a fairly reasonable way, I believe.) (Disclaimer: I don't really understand the magic behind multiple entry points in code components, so my explanation may be woefully incomplete.) > > ; 5F: C20400 RET 4 > > ; 62: 0000 ADD [EAX], AL > > ; 64: 0000 ADD [EAX], AL > > ; 66: 0000 ADD [EAX], AL > > ; 68: .ENTRY SQUARE(X) ; (FUNCTION > > ; (T) ..) > > ; 80: 8F45F8 POP DWORD PTR [EBP-8] > > but in this case it's just zeroes so the disassembly still syncs up. Or maybe the zeroes are just padding so that the entry starts on a doubleword boundary? > I have a "fix" I kludged up for this in the disassem-patch.lisp I load > here (along with some code lifted from CMUCL's current disassem.lisp to > find the beginning of the disassembly without resorting to looking at > names) so the DISASSEMBLE output starts at the right place. I think the above tweak to %SIMPLE-EVAL achieves the same thing. Tested (in slime, even): CL-USER> (sb-disassem::disassemble-code-component (symbol-function 'square)) ; 0B8B7718: .ENTRY SQUARE(X) ; (FUNCTION ; (T) *) ; 30: 8F45F8 POP DWORD PTR [EBP-8] ; 33: 8D65E0 LEA ESP, [EBP-32] ; 36: 894DF4 MOV [EBP-12], ECX ; 39: 8BF2 MOV ESI, EDX ; 3B: 8975F0 MOV [EBP-16], ESI ; 3E: 8B45F4 MOV EAX, [EBP-12] ; 41: 83F804 CMP EAX, 4 ; 44: 751A JNE L0 ; 46: 8BD6 MOV EDX, ESI ; 48: 8BFE MOV EDI, ESI ; 4A: E8E48A74F5 CALL #x1000233 ; GENERIC-* ; 4F: 0F42E3 CMOVB ESP, EBX ; 52: 8B75F0 MOV ESI, [EBP-16] ; 55: 8D65F8 LEA ESP, [EBP-8] ; 58: F8 CLC ; 59: 8B6DFC MOV EBP, [EBP-4] ; 5C: C20400 RET 4 ; 5F: 90 NOP ; 60: L0: CC0A BREAK 10 ; error trap ; 62: 02 BYTE #X02 ; 63: 18 BYTE #X18 ; INVALID-ARG-COUNT-ERROR ; 64: 0D BYTE #X0D ; EAX -- Nathan | From Man's effeminate slackness it begins. --Paradise Lost The last good thing written in C was Franz Schubert's Symphony Number 9. --Erwin Dieterich |