This is a bunch of commits squashed into one per Josh's request.
add dynamicTable field
add invokedynamic instruction
add defaultDynamic bootimage field
add dummy invokedynamic support in bootimage-generator
add defaultDynamic thunk
check dynamicTable offset
comment defaultDynamicThunk to fix unused function
comment defaultDynamicThunk to fix unused function
add dynamicTable / dynamicIndex stuff
comment dynamicIndex and dynamicTable
add invokedynamic instruction impl
stub out addDynamic
unstub addDynamic
don't allow tail calls in invokedynamic
implement stub JVM_GetTemporaryDirectory method
(build broken) begin add InvokeDynamicTest
Revert "(build broken) begin add InvokeDynamicTest"
This reverts commit 77f9c54e32ac66d0803eeab93e4a10d3541987a8.
add InternalError
add URLClassPath.c for openjdk-src builds
implement stub JVM_KnownToNotExist and JVM_GetResourceLookupCache methods
intercept open0 / open for openjdk
add basic java/lang/invoke stubs
remove non-public java/lang/invoke classes
fix invokedynamic example building
<wip debugging>
such as %s, %d, %x... also width, left justify, zerofill flags are
implemented. Many of the other formats do not work, see the comments in
avian.FormatString javadoc and look for FIXME and TODO items for more
information on features that are known to not work correctly.
In afbd4ff, I made a low-risk, but very specific fix for a more
general problem: "bootstrap" classes (i.e. classes which the VM has
built-in knowledge of) need to be loaded from the classpath before any
of their methods are called. Based on recent testing, I found there were
more cases than I previously thought where the VM tries to call methods on
"unloaded" bootstrap classes, so we needed a more general solution to
the problem.
This commit addresses it by closing the last (known) loophole by which
methods might be called on bootstrap classes: invokeinterface, and its
helper method findInterfaceMethod. The fix is to check for bootstrap
classes in findInterfaceMethod and load the full versions if
necessary. This process may lead to garbage collection and/or thrown
exceptions, which made me nervous about cases of direct or indirect
calls to findInterfaceMethod not expecting those events, which is why
I hadn't used that approach earlier. However, it turns out there were
only a few places that made non-GC-safe calls to findInterfaceMethod,
and a bit of code rearrangement fixed that.
This method ends up defering to JVM_GetClassDeclaredMethods, which
creates an array of java.lang.reflect.Method instances and then
calling getName on each one through the java.lang.reflect.Member
interface. However, Method is a "bootstrap" class, meaning the VM has
built-in knowledge of it and includes a tentative version built-in but
must load the real version from the classpath at runtime before
invoking methods on it. Normally this happens naturally when Method
instances are created in Java code, but here we're creating them in
the VM instead, which doesn't automatically cause the real class to be
loaded. So we must do so explicitly.
When we initialize the vtables for bootstrap Java classes such as
java.lang.NullPointerException (i.e. classes which the VM has built-in
knowledge of), we assign the superclass's vtable to any class which
has no declared virtual methods of its own. However, that vtable will
be null if we haven't initialized the superclass yet. Therefore, we
must order this process such that no class is initialized until after
all its superclasses.
Lots has changed since we forked Android's libcore, so merging the
latest upstream code has required extensive changes to the
Avian/Android port.
One big change is that we now use Avian's versions of
java.lang.Object, java.lang.Class, java.lang.ClassLoader, some
java.lang.reflect.* classes, etc. instead of the Android versions.
The main reason is that the Android versions have become very
Dex/Dalvik-specific, and since Avian is based on Java class files, not
dex archives, that code doesn't make sense here. This has the side
benefit that we can share more native code with classpath-avian.cpp
and reduce the amount of Java/C++ code duplication.
So there I was, planning to just fix one little bug: Thread.holdsLock
and Thread.yield were missing for the Android class library. Easy
enough, right? So, I added a test, got it passing, and figured I'd go
ahead and run ci.sh with all three class libraries. Big mistake.
Here's the stuff I found:
* minor inconsistency in README.md about OpenSSL version
* untested, broken Class.getEnclosingMethod (reported by Josh)
* JNI test failed for tails=true Android build
* Runtime.nativeExit missing for Android build
* obsolete assertion in CallEvent broke tails=true Android build
* obsolete superclass field offset padding broke bootimage=true Android build
* runtime annotation parsing broke bootimage=true Android build
(because we couldn't modify Addendum.annotationTable for classes in
the heap image)
* ci.sh tried building with both android=... and openjdk=..., which
the makefile rightfully balked at
Sorry this is all in a single commit; I didn't expect so many
unrelated issues, and I'm too lazy to break them apart.
This allows them to be shared between the Avian and Android class
library builds.
This commit also disables the URL test in Misc.java on Android, since
it's known to fail, and we still want to know whether the other tests
pass.
There was a test in Strings.java that assumed the default character
encoding was UTF-8, which is an invalid assumption on some platforms
(e.g. Windows). This modifies the test to specify the encoding
explicitly.
There are two important things here:
* We only want to run "jdk-test" if we were running "test" for everything else.
This gets around a bug where jdk-test fails for cross-compile builds (where JNI is involved)
* We can specify a different test target by setting the "test" environment variable.
This is useful for cross-compiling the tests in a docker image
(setting the test_target to "build-test")
There are two problems:
* The x86 JIT compiler requires detectFeatures, defined in the x86 assembly.
Thus it can't (currently) be built on non-x86 platforms.
For the purposes of fixing test/ci.sh, it suffices to pretend
codegen-targets=all means codegen-targets=native when on arm.
* Qemu can introduce some extra latency which was regularly screwing up the LinkedBlockingQueueTest.
Solution: increase the timeout to 1/10th seconds.
This was a bug, wherein upon throwing an exception, we would try to
allocate memory for the message - all while holding a critical
reference to the jbyteArray representing the exception string. This
caused an expect to fail in allocate3.
This ensures that all tests pass when Avian is built with an
openjdk=$path option such that $path points to either OpenJDK 7 or 8.
Note that I have not yet tried using the openjdk-src option with
OpenJDK 8. I'll work on that next.
The Misc test was failing when run as "make input=Misc run" since
test-flags did not include $(build)/extra-dir in the class library,
leading the ClassLoader.getResources test to fail.
Also, the UnknownHostException test was not reliable -- some ISPs
(mine included) return DNS matches for bogus hostnames, defaulting to
the IP address of a webserver intended to help users with name
resolution problems. That's dumb, I know, but I'm guessing I'm not
the only person with a dumb ISP, and it seems better to just remove
the test than make people think Avian is broken when it's really just
their DNS server that's broken.