Opened 13 years ago

Closed 12 years ago

#200 closed defect (fixed)

ABCL compiler fails to produce loadable fasl for XPATH

Reported by: Mark Evenson Owned by: ehuelsmann
Priority: blocker Milestone: 1.2.0
Component: compiler Version: 1.1.0
Keywords: compiler-macro quicklisp xpath jvm-class-verify-error Cc:
Parent Tickets:

Description

For the :XPATH system loaded from 2012-03-05 Quicklisp the plexippus-xpath-20110219-darcs fails to load

Compiled function can't be loaded: org.armedbear.lisp.ASDF_TMP_xpath_test_11 from org.armedbear.lisp.Pathname@40f69ae7

which results from the class verifier error

java.lang.VerifyError: (class: org/armedbear/lisp/ASDF_TMP_xpath_test_11, method: execute signature: ()Lorg/armedbear/lisp/LispObject;) Accessing value from uninitialized register 20
	at java.lang.Class.getDeclaredConstructors0(Native Method)
	at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
	at java.lang.Class.getConstructor0(Class.java:2699)
	at java.lang.Class.newInstance0(Class.java:326)
	at java.lang.Class.newInstance(Class.java:308)
	at org.armedbear.lisp.FaslClassLoader.loadFunction(FaslClassLoader.java:132)

Change History (13)

comment:1 Changed 12 years ago by Mark Evenson

Using the justIce verifier shows that the offending instruction is at position 660 of xpath_test_11.cls:

Constraint violated in method 'public final org.armedbear.lisp.LispObject execute()':
Instruction ALOAD constraint violated: Read-Access on local variable 20 with unknown content.
InstructionHandle:  660: aload[25](2) 20

comment:2 Changed 12 years ago by Mark Evenson

Priority: majorblocker

comment:3 Changed 12 years ago by Evenson Not Org

Milestone: 1.1.01.1.1

comment:4 Changed 12 years ago by Mark Evenson

Milestone: 1.1.11.2.0

comment:5 Changed 12 years ago by Mark Evenson

Version: 1.1.0-dev1.1.0

comment:6 Changed 12 years ago by charmon

If one disables the compiler-macro for evaluate as follows,

#-abcl
(define-compiler-macro evaluate (xpath context &optional unordered-p)

(once-only (xpath)

`(evaluate-compiled

(if (functionp ,xpath)

,xpath
(with-cache ((,xpath :test equal)

(*dynamic-namespaces* :test namespaces-match-p)
(*profiling-enabled-p* :test eql))

(compile-xpath ,xpath

(make-dynamic-environment

*dynamic-namespaces*))))

,context
,unordered-p)))

then xpath is happy and passes tests. I haven't yet explored to see if it's the compiler-macro itself that is the problem, or what the compiler-macro is doing, but at least we can get things to run (and pass tests) by disabling the compiler-macro.

Not the ideal fix, but perhaps a step in the right direction.

comment:7 Changed 12 years ago by charmon

Keywords: compiler-macro added

comment:8 Changed 12 years ago by ehuelsmann

Test case as identified by charmon:

(defpackage :xpath-bug

(:use :cl))

(in-package :xpath-bug)

(xpath:with-namespaces (("" ""))

(xpath:evaluate "count(html/following::text())"

(cxml:parse-rod "<html></html>"

(cxml-dom:make-dom-builder))))

comment:10 Changed 12 years ago by ehuelsmann

I'm using the following transcript to generate a failure and analyze the bytecode:

CL-USER(1): :ld c:/users/erik/quicklisp/setup.lisp
CL-USER(2): (ql:quickload :xpath)
[1] XPATH(3): 0 ;; aborts the exception handler of non-loadable code
;; Followed by pasting:
CL-USER(4): (defun my-evaluate (xpath context &optional unordered-p)

(xpath::evaluate-compiled

(if (functionp xpath)

xpath
(xpath::compile-xpath xpath (xpath::make-dynamic-environment xpath::*dynamic-namespaces*)))

context
unordered-p))

MY-EVALUATE
CL-USER(5): (define-compiler-macro my-evaluate (xpath context &optional unordered-p)

(xpath::once-only (xpath)

`(xpath::evaluate-compiled

(if (functionp ,xpath)

,xpath
(xpath::with-cache ((,xpath :test equal)

(xpath::*dynamic-namespaces* :test xpath::namespaces-match-p)
(xpath::*profiling-enabled-p* :test eql))

(xpath::compile-xpath ,xpath

(xpath::make-dynamic-environment

xpath::*dynamic-namespaces*))))

,context
,unordered-p)))

MY-EVALUATE
CL-USER(6): (SETF JVM::*COMPILER-DEBUG* T)
CL-USER(7): (COMPILE NIL '(LAMBDA () (xpath:with-namespaces (("" ""))

(my-evaluate "count(html/following::text())"

(cxml:parse-rod "<html></html>"

(cxml-dom:make-dom-builder))))))

Search the resulting bytecode listing for output along the lines of "ALOAD (20)". The 20 produces consistently on my machine, but only locals 0 to 9 have been allocated by the compiler. (To see that, evaluate "(trace jvm::allocate-register)" before compilation.)

Next question: where does that 20 come from? So far I found out that the "ALOAD 20" command is being emitted by EMIT-PUSH-VARIABLE for a variable with name "L".

comment:11 Changed 12 years ago by ehuelsmann

Forgot to mention: most of the code in the transcript is copied from https://gist.github.com/slyrus/5071736.

comment:12 Changed 12 years ago by ehuelsmann

(In [14445]) Re #200: Rewrite form-modifying macro into a series of functional-style
functions which return a modified copy instead.

comment:13 Changed 12 years ago by ehuelsmann

Resolution: fixed
Status: newclosed

Fixed by r14441 and r14445.

Note: See TracTickets for help on using tickets.