Until now, the bootimage build hasn't supported using the Java
invocation API to create a VM, destroy it, and create another in the
same process. Ideally, we would be able to create multiple VMs
simultaneously without any interference between them. In fact, Avian
is designed to support this for the most part, but there are a few
places we use global, mutable state which prevent this from working.
Most notably, the bootimage is modified in-place at runtime, so the
best we can do without extensive changes is to clean up the bootimage
when the VM is destroyed so it's ready for later instances. Hence
this commit.
Ultimately, we can move towards a fully reentrant VM by making the
bootimage immutable, but this will require some care to avoid
performance regressions. Another challenge is our Posix signal
handlers, which currently rely on a global handle to the VM, since you
can't, to my knowledge, pass a context pointer when registering a
signal handler. Thread local variables won't necessarily help, since
a thread might attatch to more than one VM at a time.
When the fourth argument is a 64-bit value on the Apple ARM ABI, it is
passed half by register and half on the stack, unlike on Linux where
it is passed entirely on the stack. The logic to handle this in arm.h
was flawed, and this commit fixes it.
This reverts commit 88d614eb25.
It turns out we still need separate sets of thunks for AOT-compiled
and JIT-compiled code to ensure we can always generate efficient jumps
and calls to thunks on architectures such as ARM and PowerPC, whose
relative jumps and calls have limited ranges.
Now that the AOT-compiled code image is position-independent, there is
no further need for this distinction. In fact, it was harmful,
because we were still using runtime-generated thunks when we should
have been using the ones in the code image. This resulted in
EXC_BAD_ACCESS errors on non-jailbroken iOS devices.
It seems that the Apple iOS Simulator's stat implementation writes
beyond the end of the struct stat we pass it, which can clobber
unrelated parts of the stack. Perhaps this is due to some kind of
header/library mismatch, but I've been unable to track it down so far.
The workaround is to give it 8 words more than it should need, where 8
is a number I just made up and seems to work.
This avoids the requirement of putting the code image in a
section/segment which is both writable and executable, which is good
for security and avoids trouble with systems like iOS which disallow
such things.
The implementation relies on relative addressing such that the offset
of the desired address is fixed as a compile-time constant relative to
the start of the memory area of interest (e.g. the code image, heap
image, or thunk table). At runtime, the base pointer to the memory
area is retrieved from the thread structure and added to the offset to
compute the final address. Using the thread pointer allows us to
generate read-only, position-independent code while avoiding the use
of IP-relative addressing, which is not available on all
architectures.
This fixes a number of bugs concerning cross-architecture bootimage
builds involving diffent endianesses. There will be more work to do
before it works.
Some apps and libraries may generate recoverable SEH exceptions on
Windows, in which cases we don't want to waste time and disk space
generating memory dumps.
The File.length() method was returning a signed 32-bit value
on 32-bit Windows systems. This was causing an integer overflow
on file sizes greater than 2 GB. This appears to be caused by
the way Windows handles the STAT() function. This patch checks
whether the current platform is Windows then uses the Windows API
to get the correct file size and return it as a jlong.