From: Alan R. <ala...@gm...> - 2007-07-14 07:50:02
|
This doesn't compile correctly. Backtrace below. Compiles and runs fine on the previous jar I was using (built from cvs within the last three months, I think) (defvar *max-java-method-args* 20 "Increase if you call java methods with more than 20 arguments") (defun argvs () (let ((get (load-time-value (jmethod (jclass "java.lang.ThreadLocal") "get"))) (argvs (load-time-value (jnew (jconstructor "java.lang.ThreadLocal")))) (null (load-time-value (make-immediate-object nil :ref)))) (let ((res (jcall-raw get argvs))) (if (equal res null) (let ((it (jnew-array "java.lang.Object" *max-java-method-args*))) (dotimes (i *max-java-method-args*) (setf (jarray-ref it i) (jnew-array "java.lang.Object" i))) (jcall (jmethod (jclass "java.lang.ThreadLocal") "set" "java.lang.Object") argvs it) it) res)))) Debugger invoked on condition of type ERROR: No such method: java.lang.Class.set("java.lang.Object") Restarts: 0: RETRY Retry performing #<ASDF:LOAD-OP (:VERBOSE NIL) {85FA36}> on #<ASDF:CL-SOURCE-FILE "invoke" {86DAF2}>. 1: ACCEPT Continue, treating #<ASDF:LOAD-OP (:VERBOSE NIL) {85FA36} > on #<ASDF:CL-SOURCE-FILE "invoke" {86DAF2}> as having been successful. [1] CL-USER(1): :bt 0: (BACKTRACE-AS-LIST) 1: (INVOKE-DEBUGGER #<ERROR {746BF0}>) 2: (JMETHOD #<JAVA-OBJECT java.lang.Class {5A8D99}> "set" "java.lang.Object") 3: (INVOKE-RESTARGS "matcher" #<JAVA-OBJECT java.util.regex.Pattern {DF85C2}> ("java.lang.management.ManagementFactory") T) 4: (#<FUNCTION (LAMBDA (OBJECT &REST ARGS)) {46BF82}> #<JAVA-OBJECT java.util.regex.Pattern {DF85C2}> "java.lang.management.ManagementFactory") 5: (LOOKUP-CLASS-NAME |java.lang.management.ManagementFactory|) 6: (MAYBE-RESOLVE-CLASS-AGAINST-IMPORTS |java.lang.management.ManagementFactory|) 7: (INVOKE-RESTARGS "getRuntimeMXBean" |java.lang.management.ManagementFactory| NIL NIL) |
From: Peter G. <pe...@ar...> - 2007-07-15 14:39:54
|
On Sat, 14 Jul 2007 at 03:49:58 -0400, Alan Ruttenberg wrote: > This doesn't compile correctly. Backtrace below. Compiles and runs > fine on the previous jar I was using (built from cvs within the last > three months, I think) The only change to the compiler in the last three months was Erik's patch to optimize the compilation of jclass, jconstructor and jmethod on May 31. -Peter |
From: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - 2007-10-08 06:57:53
|
On 10/4/07, Mark Evenson <mar...@gm...> wrote: > Peter Graves wrote: > > On Sat, 14 Jul 2007 at 03:49:58 -0400, Alan Ruttenberg wrote: > >> This doesn't compile correctly. Backtrace below. Compiles and runs > >> fine on the previous jar I was using (built from cvs within the last > >> three months, I think) > > > > The only change to the compiler in the last three months was Erik's > > patch to optimize the compilation of jclass, jconstructor and jmethod > > on May 31. > > I would argue that this patch should be retracted until it can be fixed, > as it changes the behavior of compiled functions. > > The simplest case that I could derive is TEST:JCLASS.1 from > "src/org/armedbear/lisp/test/java-tests.lisp": > > (deftest jclass.1 > (jcall (jmethod "java.lang.Object" "toString") (jclass > "java.lang.String")) > "class java.lang.String") Sorry it took me so long to address the issue, but with your reproduction case (and now finally being able to build abcl on windows), I have found a bug which is the cause of your problems. So, instead of applying your patch, I'd rather change the code the way I'll describe below. Sorry to have no patch, but I do my development work at home and I seem to be cut of from 'Net access there (mailing this from work). The problem is that the wrong class name gets written to the .cls file which is compiled from your sources, so, upon reloading the .abcl file (which loads the .cls file), a different class object is returned than the one that got written into it. The problem is in java.lisp, almost completely at the bottom in make-load-form. In the (instance-of-p "java.lang.Class" object) case, the function returns `(java:jclass ,class-name) This is incorrect, because class-name contains the name of the class of 'object' (which is a lang.java.Class). Instead, the code should retrieve the name of the class which the object is a class object for. Which should read something like this: `(java:jclass ,(jcall (jmethod "java.lang.Class" "getName") object)) [ The code above is off the top of my head, from what I found out last night. Forgive me if it's not correct. ] Could you test in your environment that the change I described above works? Thanks in advance! bye, Erik. > Understanding what is going on here has been an instructive exercise for > me to start to understand the ABCL compiler, but alas! not instructive > enough: how to fix this is beyond me at the moment. But enough to help me fix this problem! Thanks! > But if compiled > code behaves differently than interpreted code after the patch, the > patch should really not be the default. Perhaps if (> SPEED SAFETY) or > something? The attached patch does that. I don't think compiled and interpreted should behave *that* differently :-) > What I don't understand is that if I just compile a function from the > REPL like: > > (compile 'f '(lambda () (jcall (jmethod "java.lang.Object" "toString") > (jclass "java.lang.String")))) > > this returns the expected "class java.lang.String". What is different > from such an compiled function and one loaded from an 'abcl' file? If you compile a file and you want to inspect the output files, there are 2 things you can do: unzip the files and inspect them with a binary/text editor (binary for .cls files; text for .abcl files). Or you can make sure they don't get compressed by enclosing the COMPILE-FILE call in the following LET form: (let ((system:*compile-file-zip* nil)) (compile-file ...)) HTH, Erik. |
From: Alan R. <ala...@gm...> - 2007-07-16 04:28:30
|
It would make sense that that sort of change gives rise the error that is seen. Erik, would you mind taking a look? The error is during the attempt to execute (jcall (jmethod (jclass "java.lang.ThreadLocal") "set" "java.lang.Object") argvs it) -Alan On Jul 15, 2007, at 10:39 AM, Peter Graves wrote: > On Sat, 14 Jul 2007 at 03:49:58 -0400, Alan Ruttenberg wrote: >> This doesn't compile correctly. Backtrace below. Compiles and runs >> fine on the previous jar I was using (built from cvs within the last >> three months, I think) > > The only change to the compiler in the last three months was Erik's > patch to optimize the compilation of jclass, jconstructor and jmethod > on May 31. > > -Peter > |
From: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - 2007-07-16 14:49:12
|
On 7/16/07, Alan Ruttenberg <ala...@gm...> wrote: > It would make sense that that sort of change gives rise the error > that is seen. Erik, would you mind taking a look? I already got it marked down for followup. > The error is during the attempt to execute > > (jcall (jmethod (jclass "java.lang.ThreadLocal") "set" > "java.lang.Object") argvs it) So, if I understand you correctly, you want to call java.lang.ThreadLocal.set for the object contained in argvs with the 'it' argument which is supposedly of type java.lang.Object? Hmm. I indeed will need to have a longer look at this. Especially since (jmethod ...) has with the new optimization already become a load-time-value. bye, Erik. |
From: Alan R. <ala...@gm...> - 2007-07-16 15:46:13
|
On Jul 16, 2007, at 10:49 AM, XXXXXXXXXXXXXX wrote: > On 7/16/07, Alan Ruttenberg <ala...@gm...> wrote: >> It would make sense that that sort of change gives rise the error >> that is seen. Erik, would you mind taking a look? > > I already got it marked down for followup. > >> The error is during the attempt to execute >> >> (jcall (jmethod (jclass "java.lang.ThreadLocal") "set" >> "java.lang.Object") argvs it) > > So, if I understand you correctly, you want to call > java.lang.ThreadLocal.set for the object contained in argvs with the > 'it' argument which is supposedly of type java.lang.Object? Yes. See http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ ThreadLocal.html I also want, more generally speaking, the code I wrote before optimization that worked, to work after the optimization is in place. > Hmm. I indeed will need to have a longer look at this. Especially > since (jmethod ...) has with the new optimization already become a > load-time-value. Thanks Erik, -Alan |
From: Mark E. <mar...@gm...> - 2007-10-04 14:39:53
Attachments:
abcl-jclass-patch.diff
|
Peter Graves wrote: > On Sat, 14 Jul 2007 at 03:49:58 -0400, Alan Ruttenberg wrote: >> This doesn't compile correctly. Backtrace below. Compiles and runs >> fine on the previous jar I was using (built from cvs within the last >> three months, I think) > > The only change to the compiler in the last three months was Erik's > patch to optimize the compilation of jclass, jconstructor and jmethod > on May 31. I would argue that this patch should be retracted until it can be fixed, as it changes the behavior of compiled functions. The simplest case that I could derive is TEST:JCLASS.1 from "src/org/armedbear/lisp/test/java-tests.lisp": (deftest jclass.1 (jcall (jmethod "java.lang.Object" "toString") (jclass "java.lang.String")) "class java.lang.String") Under ABCL CVS HEAD, this test will now fail for compiled code that is loaded from a 'abcl' file returning: "class java.lang.Class" Essentially the JVM:P2-JAVA-JCLASS conditions for compiling to a getstatic opcode are not correct for the case for that the result will be used as an class reference for functions like JCALL or JMETHOD. Making JavaObject.getObject() return the wrapped object if it is an instance of 'java.lang.Class' would fix this, but this seems like it might break other reflective code. Understanding what is going on here has been an instructive exercise for me to start to understand the ABCL compiler, but alas! not instructive enough: how to fix this is beyond me at the moment. But if compiled code behaves differently than interpreted code after the patch, the patch should really not be the default. Perhaps if (> SPEED SAFETY) or something? The attached patch does that. What I don't understand is that if I just compile a function from the REPL like: (compile 'f '(lambda () (jcall (jmethod "java.lang.Object" "toString") (jclass "java.lang.String")))) this returns the expected "class java.lang.String". What is different from such an compiled function and one loaded from an 'abcl' file? -- <Mar...@gm...> "[T]his is not a disentanglement from, but a progressive knotting into." |
From: Mark E. <mar...@gm...> - 2007-10-08 09:50:31
Attachments:
abcl-compile-erik.diff
|
XXXXXXXXXXXXXX wrote: > This is incorrect, because class-name contains the name of the class > of 'object' (which is a lang.java.Class). Instead, the code should > retrieve the name of the class which the object is a class object for. > Which should read something like this: > `(java:jclass ,(jcall (jmethod "java.lang.Class" "getName") object)) > > [ The code above is off the top of my head, from what I found out last > night. Forgive me if it's not correct. ] > > Could you test in your environment that the change I described above > works? Thanks in advance! The attached patch (which is a direct transcription of Erik's code above) applied to abcl-0.0.10.8 after system load, does indeed resolve the issues on my end, and--more importantly--allows Allen Ruttenburg's JSS package to work again. -- <Mar...@gm...> "[T]his is not a disentanglement from, but a progressive knotting into." |
From: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - 2007-10-09 08:05:29
Attachments:
j.patch
|
On 10/8/07, Mark Evenson <mar...@gm...> wrote: > XXXXXXXXXXXXXX wrote: > > > This is incorrect, because class-name contains the name of the class > > of 'object' (which is a lang.java.Class). Instead, the code should > > retrieve the name of the class which the object is a class object for. > > Which should read something like this: > > `(java:jclass ,(jcall (jmethod "java.lang.Class" "getName") object)) > > > > [ The code above is off the top of my head, from what I found out last > > night. Forgive me if it's not correct. ] > > > > Could you test in your environment that the change I described above > > works? Thanks in advance! > > The attached patch (which is a direct transcription of Erik's code > above) applied to abcl-0.0.10.8 after system load, does indeed resolve > the issues on my end, and--more importantly--allows Allen Ruttenburg's > JSS package to work again. > > > -- > <Mar...@gm...> > > "[T]his is not a disentanglement from, but a progressive knotting into." > > > *** /home/evenson/src/j/src/org/armedbear/lisp/java.lisp Tue Sep 25 17:36:39 2007 > --- java.lisp Mon Oct 8 11:48:59 2007 > *************** > *** 216,223 **** > collecting > (jclass-name arg-type)))) > ((jinstance-of-p object "java.lang.Class") > ! `(java:jclass ,class-name)) > (t > ! (error "Unknown load-from for ~A" class-name))))) > > (provide "JAVA-EXTENSIONS") > --- 216,223 ---- > collecting > (jclass-name arg-type)))) > ((jinstance-of-p object "java.lang.Class") > ! `(java:jclass ,(jcall (jmethod "java.lang.Class" "getName") object))) > (t > ! (error "Unknown load-form for ~A" class-name))))) > > (provide "JAVA-EXTENSIONS") In case Peter wants Unified diff, I attached the same patch in unidiff format. Bye, Erik. (I turned out to have a short moment of Net access yesterday night.) |
From: Peter G. <pe...@ar...> - 2007-10-12 17:25:41
|
On Tue, 9 Oct 2007 at 10:05:27 +0200, XXXXXXXXXXXXXX wrote: > In case Peter wants Unified diff, I attached the same patch in unidiff format. Committed. Thanks! -Peter |
From: Mark E. <mar...@gm...> - 2007-10-08 10:00:57
|
XXXXXXXXXXXXXX wrote: >> What I don't understand is that if I just compile a function from the >> REPL like: >> >> (compile 'f '(lambda () (jcall (jmethod "java.lang.Object" "toString") >> (jclass "java.lang.String")))) >> >> this returns the expected "class java.lang.String". What is different >> from such an compiled function and one loaded from an 'abcl' file? > > If you compile a file and you want to inspect the output files, there > are 2 things you can do: unzip the files and inspect them with a > binary/text editor (binary for .cls files; text for .abcl files). Or > you can make sure they don't get compressed by enclosing the > COMPILE-FILE call in the following LET form: > > (let ((system:*compile-file-zip* nil)) > (compile-file ...)) My problem is not getting the compiled representation after its been written to disk. I mean getting at the representation after a function has been compiled, but not written to an *.abcl: CL-USER> (defun foo () 1) FOO CL-USER> (type-of #'foo) FUNCTION CL-USER> (compile 'foo) FOO NIL NIL CL-USER> (type-of #'foo) COMPILED-FUNCTION CL-USER> One could construct a tool that uses the byte-code representation available from: CL-USER> (getf (system:function-plist #'foo) 'system:class-bytes) but since I didn't see an easy way to do this other than serializing the bytes to disk, and calling the dissassembler anyways, I didn't really pursue the task. Note to future ABCL compiler hackers (including myself): a useful utility would be to create a decent java-byte code dissassembler as ABCL Lisp code. Most of the work is already present in 'jvm.lisp'. -- <Mar...@gm...> "[T]his is not a disentanglement from, but a progressive knotting into." |
From: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - 2007-10-08 10:05:53
|
On 10/8/07, Mark Evenson <mar...@gm...> wrote: > XXXXXXXXXXXXXX wrote: > > >> What I don't understand is that if I just compile a function from the > >> REPL like: > >> > >> (compile 'f '(lambda () (jcall (jmethod "java.lang.Object" "toString") > >> (jclass "java.lang.String")))) > >> > >> this returns the expected "class java.lang.String". What is different > >> from such an compiled function and one loaded from an 'abcl' file? > > > > If you compile a file and you want to inspect the output files, there > > are 2 things you can do: unzip the files and inspect them with a > > binary/text editor (binary for .cls files; text for .abcl files). Or > > you can make sure they don't get compressed by enclosing the > > COMPILE-FILE call in the following LET form: > > > > (let ((system:*compile-file-zip* nil)) > > (compile-file ...)) > > My problem is not getting the compiled representation after its been > written to disk. I mean getting at the representation after a function > has been compiled, but not written to an *.abcl: > > CL-USER> (defun foo () 1) > FOO > CL-USER> (type-of #'foo) > FUNCTION > CL-USER> (compile 'foo) > FOO > NIL > NIL > CL-USER> (type-of #'foo) > COMPILED-FUNCTION > CL-USER> > > One could construct a tool that uses the byte-code representation > available from: > > CL-USER> (getf (system:function-plist #'foo) 'system:class-bytes) > > but since I didn't see an easy way to do this other than serializing the > bytes to disk, and calling the dissassembler anyways, I didn't really > pursue the task. Note to future ABCL compiler hackers (including > myself): a useful utility would be to create a decent java-byte code > dissassembler as ABCL Lisp code. Most of the work is already present > in 'jvm.lisp'. You are aware that there's a facility built into abcl which uses JAD (http://www.kpdus.com/jad.html) as the disassembler? It's underdocumented (I learned about it when chatting on IRC with Peter), but if jad is on your path, abcl calls it to generate (disassemble ) output. HTH, Erik. |
From: Mark E. <mar...@gm...> - 2007-10-08 11:31:52
|
XXXXXXXXXXXXXX wrote: > You are aware that there's a facility built into abcl which uses JAD > (http://www.kpdus.com/jad.html) as the disassembler? It's > underdocumented (I learned about it when chatting on IRC with Peter), > but if jad is on your path, abcl calls it to generate (disassemble ) > output. I had stumbled across the support for a disassembler in my poking around, but I hadn't understood that it would give the byte-code for a compiled class (my use case) that doesn't have an associated *.abcl. jad is a fantastic tool (probably best jvm decompiler out there), but since it's closed-source, it gets updated when its author feels the urge, so it is beginning to show its age with post-jdk-1.5 byte code (the 'ldc1' opcode no longer exists, enumerations are not understood, etc. See [1] for the only semi-normative list that I know of). This is not quite an argument for writing a decompiler/disassembler in Lisp, I know, but it would be a neat project. [1]: http://java.sun.com/docs/books/jvms/second_edition/jvms-clarify.html -- <Mar...@gm...> "[T]his is not a disentanglement from, but a progressive knotting into." |