[aarch64-port-dev ] Fix bootstrap failure in JDK9
Andrew Haley
aph at redhat.com
Tue Jul 29 10:30:41 UTC 2014
I spent yesterday tracking down a bootstrap failure building JDK9 with
JDK8. The symptom was a very odd error message about overflow when
compiling some auto-generated Java source files. These Java source
files are generated by the bootstrap (JDK8) compiler, The bug only
seemed to occur when the bootstrap JDK8 was a release build.
After a long time, I found that the bug was this line:
unsigned long uimm = labs(imm);
It looks reasonable, but it's actually incorrect. Here's the
specification:
The abs, labs, and llabs functions compute the absolute value of an
integer j. If the result cannot be represented, the behavior is
undefined. 256)
256) The absolute value of the most negative number cannot be
represented in two’s complement.
So, if the number passed to labs() is the most negative integer,
you're doomed. And this means that the abs, labs, and llabs functions
cannot be used safely unless you know the range of the argument.
Fixed thusly. I've written some versions of abs() that do not
overflow, no matter what the range of their arguments.
Note that Java's Math.abs() is well-defined for all arguments. Java
is thus better than C and C++. But we knew that already. :-)
Andrew.
# HG changeset patch
# User aph
# Date 1406628026 14400
# Tue Jul 29 06:00:26 2014 -0400
# Node ID 5e238903a8753fdca06994bec8b36363ae930664
# Parent 4020f25a52c21258ee7daaa878ec5196344a6b1e
Define uabs(). Use it everywhere an absolute value is wanted.
diff -r 4020f25a52c2 -r 5e238903a875 src/cpu/aarch64/vm/assembler_aarch64.cpp
--- a/src/cpu/aarch64/vm/assembler_aarch64.cpp Fri Jul 25 08:17:44 2014 -0400
+++ b/src/cpu/aarch64/vm/assembler_aarch64.cpp Tue Jul 29 06:00:26 2014 -0400
@@ -1453,7 +1453,7 @@
bool Assembler::operand_valid_for_add_sub_immediate(long imm) {
bool shift = false;
- unsigned long uimm = labs(imm);
+ unsigned long uimm = uabs(imm);
if (uimm < (1 << 12))
return true;
if (uimm < (1 << 24)
diff -r 4020f25a52c2 -r 5e238903a875 src/cpu/aarch64/vm/assembler_aarch64.hpp
--- a/src/cpu/aarch64/vm/assembler_aarch64.hpp Fri Jul 25 08:17:44 2014 -0400
+++ b/src/cpu/aarch64/vm/assembler_aarch64.hpp Tue Jul 29 06:00:26 2014 -0400
@@ -320,6 +320,29 @@
enum operation { uxtb, uxth, uxtw, uxtx, sxtb, sxth, sxtw, sxtx };
};
+// abs methods which cannot overflow and so are well-defined across
+// the entire domain of integer types.
+static inline unsigned int uabs(unsigned int n) {
+ union {
+ unsigned int result;
+ int value;
+ };
+ result = n;
+ if (value < 0) result = -result;
+ return result;
+}
+static inline unsigned long uabs(unsigned long n) {
+ union {
+ unsigned long result;
+ long value;
+ };
+ result = n;
+ if (value < 0) result = -result;
+ return result;
+}
+static inline unsigned long uabs(long n) { return uabs((unsigned long)n); }
+static inline unsigned long uabs(int n) { return uabs((unsigned int)n); }
+
// Addressing modes
class Address VALUE_OBJ_CLASS_SPEC {
public:
@@ -547,7 +570,7 @@
static bool offset_ok_for_immed(long offset, int shift = 0) {
unsigned mask = (1 << shift) - 1;
if (offset < 0 || offset & mask) {
- return (abs(offset) < (1 << (20 - 12))); // Unscaled offset
+ return (uabs(offset) < (1 << (20 - 12))); // Unscaled offset
} else {
return ((offset >> shift) < (1 << (21 - 10 + 1))); // Scaled, unsigned offset
}
@@ -618,6 +641,7 @@
#endif
public:
+
enum { instruction_size = 4 };
Address adjust(Register base, int offset, bool preIncrement) {
diff -r 4020f25a52c2 -r 5e238903a875 src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Fri Jul 25 08:17:44 2014 -0400
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Tue Jul 29 06:00:26 2014 -0400
@@ -1796,7 +1796,7 @@
if (operand_valid_for_add_sub_immediate((int)imm)) {
(this->*insn1)(Rd, Rn, imm);
} else {
- if (labs(imm) < (1 << 24)) {
+ if (uabs(imm) < (1 << 24)) {
(this->*insn1)(Rd, Rn, imm & -(1 << 12));
(this->*insn1)(Rd, Rd, imm & ((1 << 12)-1));
} else {
@@ -3292,7 +3292,7 @@
void MacroAssembler::adrp(Register reg1, const Address &dest, unsigned long &byte_offset) {
relocInfo::relocType rtype = dest.rspec().reloc()->type();
- if (labs(pc() - dest.target()) >= (1LL << 32)) {
+ if (uabs(pc() - dest.target()) >= (1LL << 32)) {
guarantee(rtype == relocInfo::none
|| rtype == relocInfo::external_word_type
|| rtype == relocInfo::poll_type
diff -r 4020f25a52c2 -r 5e238903a875 src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
--- a/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Fri Jul 25 08:17:44 2014 -0400
+++ b/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Tue Jul 29 06:00:26 2014 -0400
@@ -899,7 +899,7 @@
void copy_memory_small(Register s, Register d, Register count, Register tmp, int step) {
bool is_backwards = step < 0;
- size_t granularity = abs(step);
+ size_t granularity = uabs(step);
int direction = is_backwards ? -1 : 1;
int unit = wordSize * direction;
@@ -955,7 +955,7 @@
Register count, Register tmp, int step) {
copy_direction direction = step < 0 ? copy_backwards : copy_forwards;
bool is_backwards = step < 0;
- int granularity = abs(step);
+ int granularity = uabs(step);
const Register t0 = r3, t1 = r4;
if (is_backwards) {
More information about the aarch64-port-dev
mailing list