"%*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.
We must use separate va_start/va_end pairs for each call to vsnprintf
on Linux and possibly other platforms in order to avoid a crash.
Also, we need to give it room to null terminate the string at the
right point.
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.
The original stub implementation just echoed back its argument, but
that confused URLClassLoader when dealing with sealed JARs --
returning a non-null value for a non-system class from
JVM_GetSystemPackage made URLClassloader think it had already loaded a
class from a package which was supposed to be sealed, resulting in
SecurityExceptions which ultimately triggered NoClassDefFoundErrors.
The solution is to only return non-null values for actual system
classes.
We weren't wrapping exceptions thrown by invoked methods in
InvocationTargetExceptions in JVM_InvokeMethod or
JVM_NewInstanceFromConstructor. Also, JVM_GetCallerClass is supposed
to ignore Method.invoke frames when walking the stack.
My earlier fix (f8e8609) was almost -- but not quite -- sufficient.
It asked the heap to mark the dead fixies too early, so some of them
were marked dead even though they ultimately survived, causing us to
clear weak JNI references when we shouldn't.
The existing code did not handle static field lookups for
synchronization on 32-bit systems, which is necessary because such
systems generally don't support atomic operations on 64-bit values.
Recent versions of IcedTea will not run unless libjvm.so exports this
symbol. The quick fix is to provide a stub which just always returns
-1 to indicate an error. I'll leave a proper implementation for when
we need to support an app that actually uses this function.
My earlier commit to allow detaching the main thread (1f1c3c4) seems
to have caused subtle stability problems
(e.g. https://groups.google.com/group/avian/msg/d2c797c0dcf925c3), so
for now we'll just ignore that operation, which leaks a bit of memory
but should be harmless otherwise.
set java.vm.version based on makefile version=
in order to display relevant OpenJDK -version information.
Signed-off-by: Matthias Klose <doko@ubuntu.com>
Signed-off-by: Xerxes Rånby <xerxes@zafena.se>
My earlier attempt (fa5d76b) missed an important detail, and somehow I
forgot to test the 32-bit OpenJDK build which made that omission
obvious. Here's the fix.
resolveClass was correctly respecting throw_ == false if the requested
class was not found, but it still threw an exception if e.g. the
superclass was missing. Now we catch such exceptions and return null
as appropriate.
Some apps refuse to run if Runtime.maxMemory returns a value that's
"too small", so our stub implementation returning zero was not
sufficient. Now we return the actual heap size limit in bytes.
sun.misc.Launcher has its own idea about what the application
classloader should be, but we need to override it with the system
classloader created by the VM. This is achieved by running
Launcher.getLauncher (which has the side effect of setting
Thread.contextClassLoader) and then overriding it.
When I originally implemented DetachCurrentThread, I assumed it didn't
make sense for the main thread to detach itself from the VM, and I was
concerned that allowing it might cause problems for any other threads
still attached. However, detaching the main thread is allowed by the
JNI spec as of Java 2, and OpenJDK's java command does this just
before calling DestroyJavaVM. Therefore, this commit ensures that the
VM doesn't abort if the main thread is detached.
We weren't adding entries to the frame map for calls to the instanceof
thunk when compiling methods. However, that thunk may trigger a GC,
in which case we'll need to unwind the stack, which will lead to a
crash if we don't have a frame map entry for that instruction.
Java requires that NaNs be converted to zero and that numbers at or
beyond the limits of integer representation be clamped to the largest
or smallest value that can be represented, respectively.
Our implementation uses Object.wait(long) to implement Thread.sleep,
which had the side effect of interpreting zero as infinity. However,
for Thread.sleep, zero just means zero. I assume that doesn't mean
"don't sleep at all", though, or else the app wouldn't have called
Thread.sleep in the first place, so this patch sleeps for one
millisecond when zero is passed -- just enough to yield the processor
for a bit. Thread.yield might be a better choice in this case, but I
assume the app would have called that directly if that's what it
wanted.
This led to fixed-position objects being considered unreachable when
they were actually still reachable, causing global weak JNI references
to be cleared prematurely, most notably leading to crashes in AWT
buffered image code.
This commit also fixes a field offset calculation mismatch in
bootimage.cpp relative to machine.cpp.
OpenJDK 7 has refactored this code relative to OpenJDK 6, and now
FontManager is an interface, with SunFontManager providing a (partial)
implementation.
On the ARM platform, Avian compiled to use OpenJDK gets this error on
startup:
java/lang/UnsatisfiedLinkError: no zip in java.library.path
at java/lang/ClassLoader.loadLibrary (line 1860)
at java/lang/Runtime.loadLibrary0 (line 845)
at java/lang/System.loadLibrary (line 1084)
at java/lang/System.initializeSystemClass (line 1145)
Using strace shows why:
[pid 22431]
stat64("/usr/lib/jvm/java-7-openjdk-armhf/jre/lib/i386/libzip.so",
0xbee377e0) = -1 ENOENT (No such file or directory)
The attached patch uses "arm" instead of "i386" in that path. This fixes the
problem.
Linux, FreeBSD, and QNX all use ELF, so no need to distinguish between
them when generating object files. To avoid confusion, I've switch
from using operating system names to using binary format names where
applicable.
When we skip a single-precision register to ensure a double-precision
load is aligned, we need to remember that in case we see another
single-precision argument later on, which we must backfill into that
register we skipped according to the ABI.
This ABI's calling convention passes arguments and returns results
using VFP registers, so we need to tweak vmNativeCall to match it.
Thanks to Damjan Jovanovic for pointing this out and providing an
initial patch.
The existing code handled such odd switch statements correctly in the
JIT case, but did the wrong thing for the AOT case, leading to an
assertion failure later on.
All but one test is passing. The failure is due to the fact that QNX
doesn't (in general) support calling fork(2) from a multithreaded
process. Thus, we'll need to use spawn instead of fork/exec on QNX,
which I'll attempt in a later commit.
http://www.qnx.com/developers/docs/6.4.1/neutrino/getting_started/s1_procs.html
4512a9a introduced a new ArgumentList constructor which was handling
some types incorrectly (e.g. implicitly converting floats to
integers). This commit fixes it.
We were assuming the array element size was always the native word
size, which is not correct in general for primitive arrays, and this
led to wasted space at best and memory corruption at worst.
The compiler was failing to freeze the source site containing the
value of the second word in a multi-word move, leading to mis-compiled
code in some cases.
Our Thread.getStackTrace implementation is tricky because it might be
invoked on a thread executing arbitrary native or Java code, and there
are numerous edge cases to consider. Unsurprisingly, there were a few
lingering, non-fatal bugs revealed by Valgrind recently, one involving
the brief interval just before and after returning from invokeNative,
and the other involving an off-by-one error in x86.cpp's nextFrame
implementation. This commit fixes both.
sun.misc.Unsafe now has two native getByte methods: one which takes a
long and another which takes an Object and a long. Thus, we need to
decorate each version with its parameter signature so we don't
accidentally call the wrong one at runtime.
As of the latest code from the jdk7u-dev Mercurial repository,
java.lang.String no longer has offset or length fields. Instead, the
content fits exactly into the backing char array, so offset is
implicitly zero and length is the length of the array. The VM
previously relied on those fields being present, whereas this commit
handles the case where they are not.
In addition, I've made some changes to openjdk-src.mk to ensure that
we can build against both a stock OpenJDK 7 and an IcedTea-patched
version.
If a class references a field or method as static and we find it's
actually non-static -- or vice-versa -- we ought to throw an error
rather than abort.
The usage statement for the bootimage-generator now looks like this:
build/linux-x86_64-bootimage/bootimage-generator \
-cp <classpath> \
-bootimage <bootimage file> \
-codeimage <codeimage file> \
[-entry <class name>[.<method name>[<method spec>]]] \
[-bootimage-symbols <start symbol name>:<end symbol name>] \
[-codeimage-symbols <start symbol name>:<end symbol name>]
The first problem was that, on x86, we failed to properly keep track
of whether to expect the return address to be on the stack or not when
unwinding through a frame. We were relying on a "stackLimit" pointer
to tell us whether we were looking at the most recently-called frame
by comparing it with the stack pointer for that frame. That was
inaccurate in the case of a thread executing at the beginning of a
method before a new frame is allocated, in which case the most recent
two frames share a stack pointer, confusing the unwinder. The
solution involves keeping track of how many frames we've looked at
while walking the stack.
The other problem was that compareIpToMethodBounds assumed every
method was followed by at least one byte of padding before the next
method started. That assumption was usually valid because we were
storing the size following method code prior to the code itself.
However, the last method of an AOT-compiled code image is not followed
by any such method header and may instead be followed directly by
native code with no intervening padding. In that case, we risk
interpreting that native code as part of the preceding method, with
potentially bizarre results.
The reason for the compareIpToMethodBounds assumption was that methods
which throw exceptions as their last instruction generate a
non-returning call, which nonetheless push a return address on the
stack which points past the end of the method, and the unwinder needs
to know that return address belongs to that method. A better solution
is to add an extra trap instruction to the end of such methods, which
is what this patch does.
For some reason, Cygwin's MinGW-W64 compilers end up pulling in our
version of process.h from unistd.h. That doesn't really make sense --
it should use the one from the sysroot, but we can work around it by
just not including unistd.h, since it's not needed on Windows anyway.
OpenJDK is huge, so building a bootimage out of the whole thing (as
opposed to an app shrunk using ProGuard) requires a lot of space.
Note that we still can't handle this on ARM or PowerPC due to a
limitation in the compiler, but we don't expect people to ship
binaries with the entire OpenJDK class library anyway, so it shouldn't
be a problem in practice.
If we don't initialize that at our first opportunity, it's possible
we'll run out of memory later and exit silently instead of printing
the error and returning a nonzero exit code.
It seems that GCC 4.6.1 gets confused at LTO time when we take the
address of inline functions, so I'm switching them to non-inline
linkage to make it happy.
It seems that GCC 4.6.1 gets confused at LTO time when we take the
address of inline functions, so I'm switching them to non-inline
linkage to make it happy.
The JRE lib dir for OpenJDK 7 on OS X seems to be just "lib", not
e.g. "lib/amd64" by default, so we use that now. Also, the default
library compatibility version for libjvm.dylib is 0.0.0, but OpenJDK
wants 1.0.0, so we set it explicitly.
If we clear Thread::flags before releasing the thread mutex and
re-acquiring the monitor mutex, it's possible that we will be notified
between the release and re-acquire, which will confuse us later if we
try to wait on the same monitor again such that we well not remove
ourselves from the wait list because we think we've been removed by
the notifier.
The solution is to wait until we've acquired both mutexes before we
clear Thread::flags.
We've already been handling this case in arm.cpp and powerpc.cpp, but
apparently we've never hit this code path in x86.cpp before. Indeed,
I've been unable to come up with a Java source code test that hits it;
it's only come up in Scala-generated bytecode.
Scala occasionally generates exception handler tables with interval
bounds which fall outside the range of valid bytecode indexes, so we
must clamp them or risk out-of-bounds array accesses.
Since we use Thread::code to store a reference to either the method to
be invoked or the current bytecode being executed depending on the
context, we must be careful to switch it back to the bytecode of the
exception handler if an exception is thrown while invoking a method
(e.g. an UnsatisfiedLinkError).
There was a subtle bug in that we were not considering alignment
padding for fields defined in superclasses when calculating field
offsets for a derived class when the superclass(es) were visited by
the bootimage generator before the derived class.