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 ArrayList(Collection) constructor was allocating two arrays
instead of one due to an off-by-one error in ArrayList.grow. This
commit fixes that and makes grow and shrink more robust.
We were not properly converting dots to slashes internally for package names
and we did not properly handle Method.getAnnotations and
Method.getAnnotation(Class<T>) on methods without any annotations.
Added some tests to cover these cases.
In the tails=true build, the calling method cannot always be
determined due to stack frames being optimized away, so we must be
prepared for LogRecord.getSourceMethodName to return null.
This was causing 8-byte SSE-to-SSE moves involving registers
xmm8-xmm15 to be misencoded on x86_64, leading to incorrect code
generation in methods with lots of local variables of type double.
Unlike the interpreter, the JIT compiler tries to resolve all the
symbols referenced by a method when compiling that method. However,
this can backfire if a symbol cannot be resolved: we end up throwing
an e.g. NoClassDefFoundError for code which may never be executed.
This is particularly troublesome for code which supports multiple
APIs, choosing one at runtime.
The solution is to defer to stub code for symbols which can't be
resolved at JIT compile time. Such a stub will try again at runtime
to resolve the needed symbol and throw an appropriate error if it
still can't be found.
Thread.yield is not enough to ensure that the tracing thread does not
starve the test thread on some QEMU VMs, so we use wait/notifyAll to
make sure both threads have opportunities to run and the test actually
finishes.
The VM uses Integer and Long instances internally to wrap the results
of dynamic method invocations, but Method.invoke should use the
correct, specific type for the primitive (e.g. Character for char).
My previous attempt at this was incomplete; it did not address
Java->native->Java->native call sequences, nor did it address
continuations. This commit takes care of both.
The stack mapping code was broken for cases of stack slots being
reused to hold primitives or addresses within subroutines after
previously being used to hold object references. We now bitwise "and"
the stack map upon return from the subroutine with the map as it
existed prior to calling the subroutine, which has the effect of
clearing map locations previously marked as GC roots where
appropriate.
This test covers the case where a local stack slot is first used to
store an object reference and later to store a subroutine return
address. Unfortunately, this confuses the VM's stack mapping code;
I'll be working on a fix for that next.
The new test requires generating bytecode from scratch, since there's
no reliable way to get javac to generate the code we want. Since we
already had primitive bytecode construction code in Proxy.java, I
factored it out so we can reuse it in Subroutine.java.