On 06/22/2011 06:20 PM, Andrew Haley wrote: > I've found and fixed the bugs that were stopping gcj from working. This is really impressive. Thanks for describing the details! Cheers, Niels > Firstly, there was the "libgcc is a symlink instead of a linker > script" bug that I've explained before. > > > Then there was the libgcj/sysdep/arm/locks.h problem that broke > locking. I already described that. > > > Then I found a locking bug in the boehm garbage collector. > GC_clear(), which releases a lock, was simply > > inline static void GC_clear(volatile unsigned int *addr) { > /* Try to discourage gcc from moving anything past this. */ > __asm__ __volatile__(" " : : : "memory"); > *(addr) = 0; > } > > but it needs a memory barrier instruction. The easiest way to fix > this is to use a gcc builtin that generates the correct barrier: > > inline static void GC_clear(volatile unsigned int *addr) { > __sync_lock_release(addr); > } > > I also replaced GC_test_and_set() with a gcc builtin, although this > isn't strictly necessary: > > inline static int GC_test_and_set(volatile unsigned int *addr) { > return __sync_lock_test_and_set(addr, 1); > } > > > There was also a problem in libffi when generating a closure. The > code that generates a trampoline looks like this: > > #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ > ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ > unsigned int __fun = (unsigned int)(FUN); \ > unsigned int __ctx = (unsigned int)(CTX); \ > *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \ > *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ > *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ > *(unsigned int*) &__tramp[12] = __ctx; \ > *(unsigned int*) &__tramp[16] = __fun; \ > __clear_cache((&__tramp[0]), (&__tramp[19])); \ > }) > > Here, three instructions are laid down in memory, followed by some > data fields. Once that has been done, __clear_cache() is called on > the block of memory. Unfortunately, due to the requirement to placate > SELinux, the same block of memory is mapped twice, once with RW > mapping and once with RX mapping. Therefore, there must be two calls > to __clear_cache(), one to flush the dcache, and one to flush the > icache. Like this: > > #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ > ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ > unsigned int __fun = (unsigned int)(FUN); \ > unsigned int __ctx = (unsigned int)(CTX); \ > unsigned char *insns = (unsigned char *)(CTX); \ > *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \ > *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ > *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ > *(unsigned int*) &__tramp[12] = __ctx; \ > *(unsigned int*) &__tramp[16] = __fun; \ > __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping. */ \ > __clear_cache(insns, insns + 3 * sizeof (unsigned int)); \ > /* Clear instruction \ > mapping. */ \ > }) > > > Finally, libjava was segfaulting when an array class was finalized. > This has apparently always happened, but on other platforms the > segfault is caught and turned into a NullPointerException. All > finalizers are called from an exception region that traps all > exceptions and continues, so we never noticed. > > Fixed thusly: > > --- libjava/java/lang/natClass.cc 2010-06-11 05:09:01.000000000 -0400 > +++ prev/libjava/java/lang/natClass.cc 2011-06-21 06:09:22.000000000 -0400 > @@ -668,6 +668,8 @@ > void > java::lang::Class::finalize (void) > { > + // Array classes don't have an engine, and don't need to be finalized. > + if (engine) > engine->unregister(this); > } > > > After all this, gcj now seems to work. I'm now building OpenJDK. > > Andrew. > _______________________________________________ > arm mailing list > arm@xxxxxxxxxxxxxxxxxxxxxxx > https://admin.fedoraproject.org/mailman/listinfo/arm _______________________________________________ arm mailing list arm@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/arm