We have to be careful about how we calculate return addresses on ARM
due to padding introduced by constant pools interspersed with code.
When calculating the offset of code where we're inserting a constant
pool, we want the offset of the end of the pool for jump targets, but
we want the offset just prior to the beginning of the pool (i.e. the
offset of the instruction responsible for jumping past the pool) when
calculating a return address.
Previously, loading an arbitrary 32-bit constant required up to four
instructions (128 bytes), since we did so one byte at a time via
immediate-mode operations.
The preferred way to load constants on ARM is via PC-relative
addressing, but this is challenging because immediate memory offsets
are limited to 4096 bytes in either direction. We frequently need to
compile methods which are larger than 4096, or even 8192, bytes, so we
must intersperse code and data if we want to use PC-relative loads
everywhere.
This commit enables pervasive PC-relative loads by handling the
following cases:
1. Method is shorter than 4096 bytes: append data table to end
2. Method is longer than 4096 bytes, but no basic block is longer
than 4096 bytes: insert data tables as necessary after blocks, taking
care to minimize the total number of tables
3. Method is longer than 4096 bytes, and some blocks are longer than
4096 bytes: split large basic blocks and insert data tables as above
We've been getting away with not doing this so far since our Java
calling convention matches the native calling convention concerning
where the return address is saved, so when our thunk calls native code
it gets saved for us automatically. However, there was still the
danger that a thread would interrupt another thread after the stack
pointer was saved to the thread field but before the native code was
called and try to get a stack trace, at which point it would try to
find the return address relative to that stack pointer and find
garbage instead. This commit ensures that we save the return address
before saving the stack pointer to avoid such a situation.
The shiftLeftC function in powerpc.cpp was miscompiling such shifts,
leading to crashes due to illegal instructions and other weirdness due
to instructions that meant something completely different. This
commit fixes that and adds a test to Longs.java to make sure it stays
fixed.
The SingleRead::successor field is used (when non-null) to further
constrain the SiteMask in SingleRead::intersect based on reads of
successor values (as in the cases of moves and condensed-addressing
combine and translate instructions).