8249749: modify a primitive array through a stream and a for cycle causes jre crash

Check align_to_ref for NULL early and bailout SuperWord optimization.

Reviewed-by: vlivanov, thartmann
This commit is contained in:
Vladimir Kozlov 2020-08-10 15:31:01 -07:00
parent 6cfe3fea08
commit 092389e3c9
2 changed files with 191 additions and 11 deletions
src/hotspot/share/opto
test/hotspot/jtreg/compiler/vectorization

@ -499,6 +499,10 @@ void SuperWord::SLP_extract() {
find_adjacent_refs();
if (align_to_ref() == NULL) {
return; // Did not find memory reference to align vectors
}
extend_packlist();
if (_do_vector_loop) {
@ -575,6 +579,9 @@ void SuperWord::find_adjacent_refs() {
}
}
}
if (TraceSuperWord) {
tty->print_cr("\nfind_adjacent_refs found %d memops", memops.size());
}
Node_List align_to_refs;
int max_idx;
@ -3229,15 +3236,15 @@ void SuperWord::compute_vector_element_type() {
//------------------------------memory_alignment---------------------------
// Alignment within a vector memory reference
int SuperWord::memory_alignment(MemNode* s, int iv_adjust) {
#ifndef PRODUCT
if(TraceSuperWord && Verbose) {
tty->print("SuperWord::memory_alignment within a vector memory reference for %d: ", s->_idx); s->dump();
}
#endif
#ifndef PRODUCT
if ((TraceSuperWord && Verbose) || is_trace_alignment()) {
tty->print("SuperWord::memory_alignment within a vector memory reference for %d: ", s->_idx); s->dump();
}
#endif
NOT_PRODUCT(SWPointer::Tracer::Depth ddd(0);)
SWPointer p(s, this, NULL, false);
if (!p.valid()) {
NOT_PRODUCT(if(is_trace_alignment()) tty->print("SWPointer::memory_alignment: SWPointer p invalid, return bottom_align");)
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SWPointer::memory_alignment: SWPointer p invalid, return bottom_align");)
return bottom_align;
}
int vw = get_vw_bytes_special(s);
@ -3249,9 +3256,11 @@ int SuperWord::memory_alignment(MemNode* s, int iv_adjust) {
offset += iv_adjust*p.memory_size();
int off_rem = offset % vw;
int off_mod = off_rem >= 0 ? off_rem : off_rem + vw;
if (TraceSuperWord && Verbose) {
#ifndef PRODUCT
if ((TraceSuperWord && Verbose) || is_trace_alignment()) {
tty->print_cr("SWPointer::memory_alignment: off_rem = %d, off_mod = %d", off_rem, off_mod);
}
#endif
return off_mod;
}
@ -3766,6 +3775,7 @@ bool SWPointer::invariant(Node* n) {
NOT_PRODUCT(_tracer.invariant_1(n, n_c);)
return !lpt()->is_member(phase()->get_loop(n_c));
}
//------------------------scaled_iv_plus_offset--------------------
// Match: k*iv + offset
// where: k is a constant that maybe zero, and
@ -3786,20 +3796,20 @@ bool SWPointer::scaled_iv_plus_offset(Node* n) {
int opc = n->Opcode();
if (opc == Op_AddI) {
if (scaled_iv(n->in(1)) && offset_plus_k(n->in(2))) {
if (offset_plus_k(n->in(2)) && scaled_iv_plus_offset(n->in(1))) {
NOT_PRODUCT(_tracer.scaled_iv_plus_offset_4(n);)
return true;
}
if (scaled_iv(n->in(2)) && offset_plus_k(n->in(1))) {
if (offset_plus_k(n->in(1)) && scaled_iv_plus_offset(n->in(2))) {
NOT_PRODUCT(_tracer.scaled_iv_plus_offset_5(n);)
return true;
}
} else if (opc == Op_SubI) {
if (scaled_iv(n->in(1)) && offset_plus_k(n->in(2), true)) {
if (offset_plus_k(n->in(2), true) && scaled_iv_plus_offset(n->in(1))) {
NOT_PRODUCT(_tracer.scaled_iv_plus_offset_6(n);)
return true;
}
if (scaled_iv(n->in(2)) && offset_plus_k(n->in(1))) {
if (offset_plus_k(n->in(1)) && scaled_iv_plus_offset(n->in(2))) {
_scale *= -1;
NOT_PRODUCT(_tracer.scaled_iv_plus_offset_7(n);)
return true;
@ -3871,6 +3881,7 @@ bool SWPointer::scaled_iv(Node* n) {
int mult = 1 << n->in(2)->get_int();
_scale = tmp._scale * mult;
_offset += tmp._offset * mult;
_invar = tmp._invar;
NOT_PRODUCT(_tracer.scaled_iv_9(n, _scale, _offset, mult);)
return true;
}

@ -0,0 +1,169 @@
/*
* Copyright (c) 2020, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8249749
* @summary Test vectorization for complex address expressions
* @requires vm.compMode != "Xint"
* @run main compiler.vectorization.TestComplexAddrExpr test1
* @run main compiler.vectorization.TestComplexAddrExpr test2
* @run main compiler.vectorization.TestComplexAddrExpr test3
* @run main compiler.vectorization.TestComplexAddrExpr test4
* @run main compiler.vectorization.TestComplexAddrExpr test5
* @run main compiler.vectorization.TestComplexAddrExpr test6
*/
package compiler.vectorization;
import java.util.stream.IntStream;
public class TestComplexAddrExpr {
static final int n = 1024;
static void test1(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = 0; i < n; i++) {
data[j * n + i]++;
}
});
}
static void test2(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = n - 1; i >= 0; i--) {
data[j * n + i]--;
}
});
}
static void test3(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = 1 - n; i < 1; i++) {
data[j * n - i]++;
}
});
}
static void test4(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = 0; i >= 1 - n; i--) {
data[j * n - i]--;
}
});
}
static void test5(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = 0; i < n/2; i++) {
data[j * n + (i << 1)]++;
}
for (int i = 0; i < n/2; i++) {
data[j * n + i * 2 + 1]++;
}
});
}
static void test6(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = (n - 1)/2; i >= 0; i--) {
data[j * n + (i << 1)]--;
}
for (int i = (n - 1)/2; i >= 0; i--) {
data[j * n + i * 2 + 1]--;
}
});
}
static void verify(int[] data, int k) {
for (int i = 0; i < n * n; i++) {
if (data[i] != k) {
throw new RuntimeException(" Invalid result: data[" + i + "]: " + data[i] + " != " + k);
}
}
}
public static void main(String[] args) {
// int n = 1024;
int[] data = new int[n * n];
if (args.length == 0) {
throw new RuntimeException(" Missing test name: test1, test2, test3, test4, test5, test6");
}
if (args[0].equals("test1")) {
System.out.println(" Run test1 ...");
for (int k = 0; k < n; k++) {
test1(data);
}
verify(data, n);
System.out.println(" Finished test1.");
}
if (args[0].equals("test2")) {
System.out.println(" Run test2 ...");
for (int k = 0; k < n; k++) {
test2(data);
}
verify(data, -n);
System.out.println(" Finished test2.");
}
if (args[0].equals("test3")) {
System.out.println(" Run test3 ...");
for (int k = 0; k < n; k++) {
test3(data);
}
verify(data, n);
System.out.println(" Finished test3.");
}
if (args[0].equals("test4")) {
System.out.println(" Run test4 ...");
for (int k = 0; k < n; k++) {
test4(data);
}
verify(data, -n);
System.out.println(" Finished test4.");
}
if (args[0].equals("test5")) {
System.out.println(" Run test5 ...");
for (int k = 0; k < n; k++) {
test5(data);
}
verify(data, n);
System.out.println(" Finished test5.");
}
if (args[0].equals("test6")) {
System.out.println(" Run test6 ...");
for (int k = 0; k < n; k++) {
test6(data);
}
verify(data, -n);
System.out.println(" Finished test6.");
}
}
}