"%*s" means "at least", whereas "%.*s" means at most, and the latter
is what I intended. This only became noticable as of 9f22a70, when I
added another directory to the library path, which caused loadLibrary
to fail to find libraries in either directory.
When GetStringCritical or GetPrimitiveArrayCritical are called, the VM
cannot risk new Java heap allocations until the corresponding release
method is called because allocations may result in GC, which cannot
happen while a string or array is pinned in memory. We already have a
check for this latter in the footprint function used during GC, but
it's best to catch the problem as early as possible.
Previously, we would blithely exceed the heap ceiling and force the
next allocation to deal with the problem, including a major GC and
possible OutOfMemoryError. As of this commit, we throw an error
immediately if we find that the allocation will push us over the
ceiling.
Scala sometimes generates bytecode such that the scope of an exception
handler starts at another exception handler, e.g.:
Exception table:
from to target type
290 372 382 any
382 451 451 any
290 372 451 any
Avian's compiler was incorrectly initializing the stack frame for the
second handler in this case. This commit fixes the problem.
The instruction for 32-bit-to-64-bit sign extension on x86_32 requires
that the input value be placed in EAX and the sign extension in EDX.
However, the compiler can get confused if the input value is in memory
addressed via one of those registers and doesn't know how to move it.
This patch works around that limitation by doing the move explicitly
in MemoryEvent::compile if necessary.
Method.invoke must throw an IllegalArgumentException if it receives
the wrong number or types of arguments, and since this isn't done by
the OpenJDK class library, we must do it in the VM.
This library is placed in the xawt subdirectory of jre/lib/$arch on
POSIX systems, so it isn't found automatically when third-party
libraries which depend on it are loaded. The simplest way to ensure
that it's found seems to be to just load it when the VM starts up.
In order to calculate the initial stack map of GC roots for an
exception handler, we do a logical "and" of maps across all the
instructions contained in the try block for that handler. This is
complicated by the presence of jsr/ret instructions, though, because
instructions in a subroutine may have multiple maps associated with
them corresponding to all the paths from which execution might flow to
them.
The bug in this case was that we were using an uninitialized map in
our calculation, resulting in a map with no GC roots at all. By the
time the map was initialized, the damage had already been done. The
solution is to treat an uninitialized map as if it has roots at all
positions so that it has no effect on the calculation until it has
been initialized with real data.
Hi,
I did some more tests with my x86 QNX Avian port and found one major problem
in Avian VM while trying to run Apache Ivy. The problem manifests as
follows:
1. MySystem::Thread X is created, during its creation pthread mutex and
conditional variable are initialized
2. Program runs for some time
3. MySystem Thread X is disposed, it's memory is freed (during garbage
collection I guess)
4. Program runs for some time
5. MySystem::Thread Y is created in exactly the same memory address as
MySystem::Thread X disposed in step 3 (I suppose that's due to the way
memory allocator works in Avian)
6. During MySystem::Thread Y creation pthread mutex and conditional variable
initialization fail silently with EBUSY. QNX documentation says it means
"The given mutex was previously initialized and hasn't been destroyed."
which is correct, because it's exactly in the same memory address as mutex
and conditional variable of MySystem::Thread X and they haven't been
destroyed during MySystem::Thread X disposal
Fortunately solution for this is easy, see the attached patch. Now Apache
Ivy works without any problems.
Regards,
Stanisław Szymczyk
Some OSes (notably, Windows CE) restrict the size of the call stack
such that recursive compilation of branch instructions can lead to
stack overflow in methods with large numbers of such instructions. In
fact, a worst-case method could even lead to overflow when the stack
size limit is relatively generous.
The solution is to convert this recursion into iteration with an
explicit stack to maintain state about alternate paths through each
branch.
This package name must match the URL protocol we use for loading
embedded resources, but OpenJDK's URL class won't tolerate underscores
in a protocol name. Also, I had not updated the names of the native
methods in avian.avianvmresource.Handler, leading to
UnsatisfiedLinkErrors when they were called.
Commit c918cbc added a reference to ensure
sun.misc.Unsafe.getLongVolatile could be implemented efficiently on
32-bit platforms, but I forgot to update bootimage.cpp to account for
it.
Commit c918cbc added this reference to ensure
sun.misc.Unsafe.getLongVolatile could be implemented efficiently on
32-bit platforms. However, I neglected to ensure the reference was
updated to point to the final class instance instead of the temporary
one used in parseClass. This led to extra memory usage and
inconsistent locking behavior, plus broken bootimage builds.
If we don't clear these references, we risk finalizing objects which
can still be reached by one of the special reference types.
It's a bit of a chicken-and-egg problem. We need to visit finalizable
objects before visiting weak references, since some of the weak
references and/or their targets may become reachable once the
finalizable objects are visited. However, that ordering means we have
no efficient way of distinguishing between objects which are reachable
from one or more normal GC roots and those which are only reachable
via the finalization queue. The solution is to clear all weak
references to finalizable objects before visiting them.