--- old/src/hotspot/share/opto/mathexactnode.cpp 2018-01-12 14:21:02.095926522 +0100 +++ new/src/hotspot/share/opto/mathexactnode.cpp 2018-01-12 14:21:01.655907188 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,10 +117,25 @@ return SubHelper::will_overflow(v1, v2); } +// this method is here to avoid undefined behaviour when doing -val and val is min_jlong +// -min_jlong overflows and goes back to being min_jlong +static jlong negate_jlong(jlong val) { + if (val == min_jlong) { + return min_jlong; + } + return -val; +} + bool OverflowMulLNode::will_overflow(jlong val1, jlong val2) const { - jlong result = val1 * val2; - jlong ax = (val1 < 0 ? -val1 : val1); - jlong ay = (val2 < 0 ? -val2 : val2); + julong v1 = (julong) val1; + julong v2 = (julong) val2; + // the multiplication here is done as unsigned to avoid undefined behaviour which + // can be used by the compiler to assume that the check further down (result / val2 != val1) + // is always false and break the overflow check + julong tmp = v1 * v2; + jlong result = (jlong) tmp; + jlong ax = (val1 < 0 ? negate_jlong(val1) : val1); + jlong ay = (val2 < 0 ? negate_jlong(val2) : val2); bool overflow = false; if ((ax | ay) & CONST64(0xFFFFFFFF00000000)) {