Changeset 11837


Ignore:
Timestamp:
05/06/09 20:39:51 (13 years ago)
Author:
ehuelsmann
Message:

Fix ticket #21 finally: JVM stack inconsistency error on
inlining unwind-protect.

The issue in the earlier attempts was that p1 outcomes can only
be compiled once (first try) and that one cannot p1 the same form
twice (one needs to create a copy; second try).

Location:
trunk/abcl/src/org/armedbear/lisp
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/src/org/armedbear/lisp/compiler-pass1.lisp

    r11833 r11837  
    300300  (if (= (length form) 2)
    301301      (p1 (second form)) ; No cleanup forms: (unwind-protect (...)) => (...)
     302
     303      ;; in order to compile the cleanup forms twice (see
     304      ;; p2-unwind-protect-node), we need to p1 them twice; p1 outcomes
     305      ;; can be compiled (in the same compiland?) only once.
     306      ;;
     307      ;; However, p1 transforms the forms being processed, so, we
     308      ;; need to copy the forms to create a second copy.
    302309      (let* ((block (make-block-node '(UNWIND-PROTECT)))
    303310             ;; a bit of jumping through hoops...
     311             (unwinding-forms (p1-body (copy-tree (cddr form))))
    304312             (unprotected-forms (p1-body (cddr form)))
    305313             ;; ... because only the protected form is
     
    309317        (setf (block-form block)
    310318              `(unwind-protect ,protected-form
     319                 (progn ,@unwinding-forms)
    311320                 ,@unprotected-forms))
    312321        block)))
  • trunk/abcl/src/org/armedbear/lisp/compiler-pass2.lisp

    r11835 r11837  
    78357835      (compile-form (second form) target nil)
    78367836      (return-from p2-unwind-protect-node))
     7837
     7838    ;; The internal representation of UNWIND-PROTECT
     7839    ;; as generated by P1-UNWIND-PROTECT differs a bit
     7840    ;; from what the spec says; ours is:
     7841    ;; (UNWIND-PROTECT protected-form (progn cleanup-forms) cleanup-forms),
     7842    ;; because we need to compile the cleanup forms twice and
     7843    ;; we can compile a p1 outcome only once.
     7844    ;;
     7845    ;; We used to use JSR and RET JVM instructions to prevent
     7846    ;; duplication of output code. However, this led to JVM stack
     7847    ;; inconsistency errors
     7848    ;; (see http://trac.common-lisp.net/armedbear/ticket/21)
    78377849    (let* ((protected-form (cadr form))
    7838            (cleanup-forms (cddr form))
     7850           (unwinding-form (caddr form))
     7851           (cleanup-forms (cdddr form))
    78397852           (*register* *register*)
    78407853           (exception-register (allocate-register))
    78417854           (result-register (allocate-register))
    78427855           (values-register (allocate-register))
    7843            (return-address-register (allocate-register))
    78447856           (BEGIN-PROTECTED-RANGE (gensym))
    78457857           (END-PROTECTED-RANGE (gensym))
    78467858           (HANDLER (gensym))
    7847            (EXIT (gensym))
    7848            (CLEANUP (gensym)))
     7859           (EXIT (gensym)))
    78497860      ;; Make sure there are no leftover multiple return values from previous calls.
    78507861      (emit-clear-values)
     
    78587869          (astore values-register))
    78597870        (label END-PROTECTED-RANGE))
    7860       (emit 'jsr CLEANUP)
     7871      (let ((*register* *register*))
     7872        (compile-form unwinding-form nil nil))
     7873      (when (single-valued-p protected-form)
     7874        ;; otherwise, we'll load the values register below
     7875        (maybe-emit-clear-values unwinding-form))
    78617876      (emit 'goto EXIT) ; Jump over handler.
    78627877      (label HANDLER) ; Start of exception handler.
    78637878      ;; The Throwable object is on the runtime stack. Stack depth is 1.
    78647879      (astore exception-register)
    7865       (emit 'jsr CLEANUP) ; Call cleanup forms.
     7880      (let ((*register* *register*))
     7881        (dolist (subform cleanup-forms)
     7882          (compile-form subform nil nil)))
    78667883      (maybe-emit-clear-values cleanup-forms)
    78677884      (aload exception-register)
    78687885      (emit 'athrow) ; Re-throw exception.
    7869       (label CLEANUP) ; Cleanup forms.
    7870       ;; Return address is on stack here.
    7871       (astore return-address-register)
    7872       (dolist (subform cleanup-forms)
    7873         (compile-form subform nil nil))
    7874       (emit 'ret return-address-register)
    78757886      (label EXIT)
    78767887      ;; Restore multiple values returned by protected form.
Note: See TracChangeset for help on using the changeset viewer.