VMKit assertion failure

Hi everyone,

I wanted to have a closer look at VMKit because I would like to play with modifications to a JVM. I followed the instructions at

  http://vmkit.llvm.org/get_started.html

step by step and got everything compiled without much difficulty on my MacBook (running MacOS X 10.6.3). The only modification that I needed to make was to add -L/usr/X11R6/lib to LDFLAGS for compiling the GNU classpath library.

However, any attempt at running Java code with j3 results in a crash:

Assertion failed: (ctpIndex && "No constant pool index"), function j3ResolveSpecialStub, file JavaRuntimeJIT.cpp, line 708.

I don't have the slightest idea what I could do about this. Suggestions are welcome!

Konrad.

Hi Konrad,

Yes, there has been an incompatibility change recently between LLVM and VMKit. Please use revision 100087 of LLVM until I find a workaround.

Also, running on Snow Leopard is untested (VMKit does not have support for GC on 64bits), but should work without a GC. You can also try to compile on 32bits.

Cheers,
Nicolas

Hi Nicolas,

Yes, there has been an incompatibility change recently between LLVM and VMKit. Please use revision 100087 of LLVM until I find a workaround.

OK, done.

Also, running on Snow Leopard is untested (VMKit does not have support for GC on 64bits), but should work without a GC. You can also try to compile on 32bits.

How would I run VMKit without GC?

Compiling for 32 bits is not an attractive option. The problem is the GNU classpath library, which has some unpleasant dependencies, in particular GTK+. I get them through MacPorts, which compiles 64-bit only on Snow Leopard. I'd have to install all that by hand to get 32-bit versions. I guess I'd rather work with a 32-bit Linux running under VirtualBox. Long live virtualization! :wink:

Konrad.

Hi Konrad,

How would I run VMKit without GC?

VMKit just falls back to malloc when it detects that the machine is 64bits.

Compiling for 32 bits is not an attractive option. The problem is the GNU classpath library, which has some unpleasant dependencies, in particular GTK+. I get them through MacPorts, which compiles 64-bit only on Snow Leopard. I’d have to install all that by hand to get 32-bit versions. I guess I’d rather work with a 32-bit Linux running under VirtualBox. Long live virtualization! :wink:

Yes, running a 32bits virtualized system should work just fine.

Nicolas

Hi Nicolas,

How would I run VMKit without GC?

VMKit just falls back to malloc when it detects that the machine is 64bits.

OK, I think I can handle that :wink:

Yes, running a 32bits virtualized system should work just fine.

I first tried something else: compiling on an older Mac (10.5, 32 bit compilers) and copy the binary over to the 64-bit Mac. Of course I ran a quick test on the 10.5 machine to make sure that it works - but it doesn't:

~/Temp> javac hello.java
~/Temp> java -cp . HelloWorld
Hello World!
~/Temp> j3 -cp . HelloWorld
terminate called without an active exception
Abort trap

Here's hello.java:

class HelloWorld
{
         public static void main(String args)
         {
            System.out.println("Hello World!");
         }
}

Any ideas?

Konrad.

Hi Konrad,

Did you compile vmkit with llvm-gcc or gcc? Did you make sure the path to GNU Classpath is correct in your configure command?

Also, you can now update to the latest revision.

Cheers,
Nicolas

Hi Nicolas,

Did you compile vmkit with llvm-gcc or gcc? Did you make sure the path to GNU Classpath is correct in your configure command?

I let the configure script of VMKit do its work and it decided to use gcc, the gcc 4.0.1 that is part of Apple's XCode distribution for MacOS 10.5. There is no llvm-gcc anywhere on my machine. Should I have one? I did install llvm without any error messages and I have a couple of llvm-* executables, but no llvm-gcc.

As for GNU classpath, I think my configuration is correct but I don't know how to verify. Here's my configure command line for VMKit:

  ./configure --with-llvmsrc=/Users/hinsen/Development/VMKit/llvm --with-llvmobj=/Users/hinsen/Development/VMKit/llvm --with-gnu-classpath-glibj=/Users/hinsen/Development/VMKit/classpath-0.97.2/lib --with-gnu-classpath-libs=/Users/hinsen/Development/VMKit/classpath-0.97.2/lib

And here's the output of "cd /Users/hinsen/Development/VMKit/classpath-0.97.2/lib; ls":

META-INF gen-classlist.sh libjavalangreflect.so
Makefile gen-classlist.sh.in libjavanet.so
Makefile.am glibj.zip libjavanio.so
Makefile.gcj gnu libjavautil.so
Makefile.in java mkcollections.pl.in
classes java.dep org
classes.1 javax resources
classes.2 libgconfpeer.so split-for-gcj.sh
compile-classes libgtkpeer.so standard.omit
copy-vmresources.sh libjavaio.so standard.omit.in
copy-vmresources.sh.in libjavalang.so sun

Also, you can now update to the latest revision.

Done - but that doesn't change anything, unfortunately.

Konrad.

Hmm, I am not getting that error message on my MacOS 10.5 machine with that same gcc. Could you run j3 in gdb and get me a backtrace?

Thanks!
Nicolas

Sure:

(gdb) bt
#0 0x950be44e in __semwait_signal ()
#1 0x950e93e6 in _pthread_cond_wait ()
#2 0x950e8dcd in pthread_cond_wait$UNIX2003 ()
#3 0x000be2d2 in mvm::Cond::wait (this=0x20527c4, l=0x2052790) at ctlock.cpp:151
#4 0x00020137 in j3::Jnjvm::waitForExit (this=0x20525a8) at Jnjvm.cpp:1225
#5 0x00001cf6 in main (argc=4, argv=0xbffff070, envp=0xbffff084) at Main.cpp:47

I'll try installing VMKit in a virtual Linux for comparison.

Konrad.

VMKit runs multiple threads (for example for GC, finalization, etc), so I need the back trace of other threads as well :slight_smile:

Thanks!
Nicolas

VMKit runs multiple threads (for example for GC, finalization, etc), so I need the back trace of other threads as well :slight_smile:

Here it comes:

Thread 4 (process 14442 thread 0x2003):
#0 0x950be44e in __semwait_signal ()
#1 0x950e93e6 in _pthread_cond_wait ()
#2 0x950e8dcd in pthread_cond_wait$UNIX2003 ()
#3 0x000be2d2 in mvm::Cond::wait (this=0x20526a4, l=0x2052670) at ctlock.cpp:151
#4 0x00092275 in mvm::VirtualMachine::enqueueStart (th=0x20200000) at Object.cpp:109
#5 0x000bea10 in mvm::thread::internalThreadStart (th=0x20200000) at ctthread.cpp:275
#6 0x950e8155 in _pthread_start ()
#7 0x950e8012 in thread_start ()

Thread 3 (process 14442 thread 0x1703):
#0 0x950be44e in __semwait_signal ()
#1 0x950e93e6 in _pthread_cond_wait ()
#2 0x950e8dcd in pthread_cond_wait$UNIX2003 ()
#3 0x000be2d2 in mvm::Cond::wait (this=0x2052614, l=0x2052630) at ctlock.cpp:151
#4 0x00092154 in mvm::VirtualMachine::finalizerStart (th=0x20100000) at Object.cpp:73
#5 0x000bea10 in mvm::thread::internalThreadStart (th=0x20100000) at ctthread.cpp:275
#6 0x950e8155 in _pthread_start ()
#7 0x950e8012 in thread_start ()

Thread 2 (process 14442 thread 0x313):
#0 0x95193136 in __semwait_signal_nocancel ()
#1 0x95192d1b in nanosleep$NOCANCEL$UNIX2003 ()
#2 0x9518c013 in usleep$NOCANCEL$UNIX2003 ()
#3 0x951a3685 in abort ()
#4 0x955eb005 in __gnu_cxx::__verbose_terminate_handler ()
#5 0x955e910c in __gxx_personality_v0 ()
#6 0x955e914b in std::terminate ()
#7 0x955e9261 in __cxa_throw ()
#8 0x000130ae in j3::JavaThread::throwException (this=0x20000000, obj=0x1bcfc00) at JavaThread.cpp:73
#9 0x0002352b in j3::Class::initialiseClass (this=0x20e5c60, vm=0x20525a8) at Jnjvm.cpp:249
#10 0x000242e5 in j3::Jnjvm::loadBootstrap (this=0x20525a8) at Jnjvm.cpp:1134
#11 0x000243f1 in j3::Jnjvm::mainJavaStart (thread=0x20000000) at Jnjvm.cpp:1246
#12 0x000bea10 in mvm::thread::internalThreadStart (th=0x20000000) at ctthread.cpp:275
#13 0x950e8155 in _pthread_start ()
#14 0x950e8012 in thread_start ()

Thread 1 (process 14442 local thread 0x2e03):
#0 0x950be44e in __semwait_signal ()
#1 0x950e93e6 in _pthread_cond_wait ()
#2 0x950e8dcd in pthread_cond_wait$UNIX2003 ()
#3 0x000be2d2 in mvm::Cond::wait (this=0x20527c4, l=0x2052790) at ctlock.cpp:151
#4 0x00020137 in j3::Jnjvm::waitForExit (this=0x20525a8) at Jnjvm.cpp:1225
#5 0x00001cf6 in main (argc=4, argv=0xbffff070, envp=0xbffff084) at Main.cpp:47

In the meantime I installed VMKit under Linux, where it works perfectly well for most applications I tried. However, I managed to crash it once:

> j3 -cp clojure-1.1.0.jar clojure.main
Stack overflow in VM code or in JNI code. If it is from
the VM, it is either from the JIT, the GC or the runtime.
This has to be fixed in the VM: VMKit makes sure that
the bottom of the stack is always available when entering
the VM.
Segmentation fault

There is no JNI code involved, so the stack overflow happens in the VM. Is this a bug in VMKit or just an indication that I need to change some parameter settings (memory size, ...)?

If you want to check this yourself, the jar file is available at

  http://clojure.googlecode.com/files/clojure-1.1.0.zip

Thanks,
   Konrad.

Hi Konrad,

I have added some diagnostic message when failing that early in the bootstrap in the VM. Please svn up and let me know what it prints.

About the SIGSEGV you get with clojure.jar, I ran the code and got the same error. After investigation, it turns out that the methods you have in that .jar are quite big (50,000 bytecodes) and the static initializer of the core__init class just crashes LLVM because the stack of the thread is not big enough.

I hate Java bytecode generators :slight_smile:

Nicolas

Does that include the bytecode generator known as javac? :wink:

Reid

Hi Nicolas,

I have added some diagnostic message when failing that early in the bootstrap in the VM. Please svn up and let me know what it prints.

It prints:

  Exception java/lang/UnsatisfiedLinkError while bootstraping VM

That looks like a JNI issue.

About the SIGSEGV you get with clojure.jar, I ran the code and got the same error. After investigation, it turns out that the methods you have in that .jar are quite big (50,000 bytecodes) and the static initializer of the core__init class just crashes LLVM because the stack of the thread is not big enough.

That's indeed a big one. It's the initialization of the standard library of a Lisp implementation.

I hate Java bytecode generators :slight_smile:

I like them. They let me use all those nice Java libraries without having to program in Java :slight_smile:

Konrad.

OK, I know why you get that UnsatisfiedLinkError. You have made symlinks of GNU Classpath libraries with the .so suffix. Since you’re on MacOS, you should do symlinks with the .dylib suffix (I notice that I’m not saying that on the webpage, I’ll fix that right now).

I’m not sure what to do about that core__init function. I will try to create a bigger stack to see if that changes anything or if LLVM inifinite loops.

Cheers,
Nicolas

OK, I know why you get that UnsatisfiedLinkError. You have made symlinks of GNU Classpath libraries with the .so suffix. Since you're on MacOS, you should do symlinks with the .dylib suffix (I notice that I'm not saying that on the webpage, I'll fix that right now).

Thanks - that did it! All my tests now run just like under Linux.

I'm not sure what to do about that core__init function. I will try to create a bigger stack to see if that changes anything or if LLVM inifinite loops.

I am rather surprised that the size of a method should have an impact on stack usage, but then I haven't looked at all at how VMKit works yet. That's my next project :slight_smile:

Konrad.

It has no impact on VMKit. The impact is on LLVM optimization passes that do recursive calls.

Cheers,
Nicolas

I see... Could those passes simply be skipped for code blocks that are too large? Ideally in LLVM, since it's LLVM that imposes the restriction? I don't know much about LLVM yet, but my first thought would be that a code handling system should be able to deal with code of any size. It may decide not to optimize unusual cases, but it certainly shouldn't crash.

Konrad.

You're right, it shouldn't crash. Can you track down which pass is
crashing and file a
bug?

-Eli

Hi Eli,

I know the pass that fails, it is MachineCSE. It stack overflows because there are too many recursive calls to processBlock (line 362 of lib/CodeGen/MachineCSE.cpp). But the recursion is here on purpose, and I am sure there are other places where LLVM makes recursive calls. Or is recursion forbidden in LLVM, and explicitly stated to be so?

Cheers,
Nicolas