Android's class library uses this to find out whether the VM supports
compareAndSwapLong natively. Avian does on all platforms, so we just
return true.
There's a small optimization in compileDirectInvoke which tries to
avoid generating calls to empty methods. However, this causes
problems for code which uses such a call to ensure a class is
initialized -- if we omit that call, the class may not be
initialized and any side effects of that initialization may not
happen when the program expects them to.
This commit ensures that the compiler only omits empty method calls
when the target class does not need initialization. It also removes
commented-out code in classpath-openjdk.cpp which was responsible for
loading libmawt proactively; that was a hack to get JogAmp to work
before we understood what the real problem was.
Previously, we used "lzma:", which worked fine on Windows (where the
path separator is ";") but not on Unix-style OSes (where the path
separator is ":"). In the latter case, the VM would parse
"[lzma:bootJar]" as a path containing two elements, "[lzma" and
"bootJar]", which is not what was intended. So now we use "lzma." as
the prefix, which works on all OSes.
armv7 and later provide weaker cache coherency models than armv6 and
earlier, so we cannot just implement memory barriers as no-ops. This
patch uses the DMB instruction (or the equivalent OS-provided barrier
function) to implement barriers. This should fix concurrency issues
on newer chips such as the Apple A6 and A7.
If you still need to support ARMv6 devices, you should pass
"armv6=true" to make when building Avian. Ideally, the VM would
detect what kind of CPU it was executing on at runtime and direct the
JIT compiler accordingly, but I don't know how to do that on ARM.
Patches are welcome, though!
When calculating field offsets in the bootimage generator, we failed
to consider alignment at inheritence boundaries (i.e. the last field
inherited by from a superclass should be followed by enough padding to
align the first non-inherited field at a machine word boundary). This
led to a mismatch between native code and Java code in terms of class
layouts, including that of java.lang.reflect.Method.
The former just defers to the latter for now, since it provides
strictly weaker guarantees. Thus it's correct to use full
volatile-style barriers, though not as efficient as it could be on
some architectures.
Clang was complaining that newIp might be used uninitialized at the
bottom of our giant, unstructured compile loop, so I initialized it
with a bogus value, which means it will at least fail consistently if
Clang is right and there really is a path by which that code is
reached without otherwise initializing newIp.
It looks like the iOS 7 SDK doesn't have GCC anymore, so we need to
use clang instead. Also, thread_act.h and thread_status.h have moved,
so I updated arm.h accordingly. That might break the build for older
SDKs, but I don't have one available at the moment. If it does break,
I'll fix it.
Unsafe.compareAndSwapLong was moved from classpath-openjdk.cpp to
builtin.cpp, but the fieldForOffset helper function was not, which
only caused problems when I tried to build for ARM. This commit moves
said helper function, along with Unsafe.getVolatileLong, which also
uses it.
Most of these regressions were simply due to testing a lot more stuff,
esp. annotations and reflection, revealing holes in the Android
compatibility code. There are still some holes, but at least the
suite is passing (except for a fragile test in Serialize.java which I
will open an issue for).
Sorry this is such a big commit; there was more to address than I
initially expected.
Method.invoke should initialize its class before invoking the method,
throwing an ExceptionInInitializerError if it fails, without wrapping
said error in an InvocationTargetException.
Also, we must initialize ExceptionInInitializerError.exception when
throwing instances from the VM, since OpenJDK's
ExceptionInInitializerError.getCause uses the exception field, not the
cause field.
This is by no means a complete support for the deserialization compliant
to the Java Language Specification, but it is better to add the support
incrementally, for better readability of the commits.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Previously, we initialized it to the boot class loader, but that is
inconsistent with Java; if compiling against OpenJDK's class library,
the context class loader is therefore initialized to the app class
loader, too.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The findResources method is supposed to enumerate all the class path
elements' matching paths' URLs, but we used to stop at the first one.
While this is good enough when the system class path contains only a
single .jar file, since b88438d2(sketch of JAR support in Finder)
supports more than a single .jar file in the class path.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When the system class path contains more than one .jar, it is quite
concievable that, say, 'META-INF/MANIFEST.MF' can be found in multiple
class path elements.
This commit teaches the working horse of class path inspection, the
Finder class, how to continue the search at a given state.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When creating an object array with more than two dimensions, the
component type was erroneously set to the base type, not the array
type of one less dimension.
This prevented Collection<Class[]>#toArray(Class[][]) from working
properly.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This mainly involved reworking the makefile to avoid conflating
Darwin/ARM builds with iOS, since we may also want to build for the
iOS Simulator, which is i386.
Note that I was only able to test this on the Simulator, since I don't
have a real iOS device to test with. Sorry if I broke something; if
so, please fix it :)
GCC now assumes by default that the stack is aligned to a 16-byte boundary in Linux x86, so let's do our part to honour that. :)
Otherwise native code that depends on the stack to be aligned to 16 bytes would seg fault (like SSE).
https://groups.google.com/forum/#!topic/avian/SyCl-Jfw2U8
Previously, I used a shell script to extract modification date ranges
from the Git history, but that was complicated and unreliable, so now
every file just gets the same year range in its copyright header. If
someone needs to know when a specific file was modified and by whom,
they can look at the Git history themselves; no need to include it
redundantly in the header.
There were two issues: the linux->darwin cross compiler is more stringent
about unused variables, and the makefile specified flags for building ON
darwin that were actually applicable whenever we are building FOR darwin.
The original implementation was based on the assumption that the
passed class would be the array element type, whereas it is actually
the array type itself.
It may leak file handles under certain circumstances to do nothing in
JVM_UnloadLibrary, but, for now, an empty implementation is more
useful than one that aborts the process.
At one point, loading libmawt ahead of time was necessary to make AWT
work, but recent versions of OpenJDK seem to take care this from Java
code, in which case loading it ahead of time causes trouble, so we
comment it out for now until we exactly when it's needed.
Previously, we would attempt to initialize a class (e.g. call its
static initializer) whenever a method in that class was called, as
well as in any of the cases listed in
http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.
However, the above approach may lead to deadlock in an app which
relies on being able to call non-static methods in parallel with a
static initializer invocation in the same class. Thus, this commit
ensures that we initialize classes only in the cases defined by the
standard.
Since park does not throw InterruptedException, we must leave the flag
set if we are interrupted while parked so that
e.g. AbstractQueuedSynchronizer can itself throw an exception if
appropriate.
This mainly moves several sun.misc.Unsafe method implementations from
classpath-openjdk.cpp to builtin.cpp so that the Avian and Android
builds can use them.
It also replaces FinalizerReference.finalizeAllEnqueued with a no-op,
since the real implementations assumes too much about how the VM
handles (or delegates) finalization.
We must be in the Active state, not the Exclusive state when calling
this method since it may execute arbitrary Java code. This fixes an
assertion failure in makeNew.
scalac may generate bytecode such that an exception is thrown within
the bounds of a handler for that exception such that the throw is the
last instruction in the method, which we weren't handling properly.
The InnerClasses attribute may have entries for classes declared
inside classes we don't care about, so we must check each entry's
outer class reference and make sure it matches the one we do care
about.