From cd8709e8e05897d131afba221970c0866b3d126d Mon Sep 17 00:00:00 2001 From: Dean Long Date: Fri, 29 Apr 2022 19:09:58 +0000 Subject: [PATCH] 8284883: JVM crash: guarantee(sect->end() <= sect->limit()) failed: sanity on AVX512 Reviewed-by: kvn, jbhateja --- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 41 ++++++++++++--- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 4 ++ src/hotspot/share/opto/memnode.cpp | 3 +- .../hotspot/jtreg/compiler/c2/ClearArray.java | 51 +++++++++++++++++++ 4 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/ClearArray.java diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 2c6af9b2b04f8..3c81ece32e949 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -5277,10 +5277,28 @@ void MacroAssembler::clear_mem(Register base, int cnt, Register rtmp, XMMRegiste int vector64_count = (cnt & (~0x7)) >> 3; cnt = cnt & 0x7; + const int fill64_per_loop = 4; + const int max_unrolled_fill64 = 8; // 64 byte initialization loop. vpxor(xtmp, xtmp, xtmp, use64byteVector ? AVX_512bit : AVX_256bit); - for (int i = 0; i < vector64_count; i++) { + int start64 = 0; + if (vector64_count > max_unrolled_fill64) { + Label LOOP; + Register index = rtmp; + + start64 = vector64_count - (vector64_count % fill64_per_loop); + + movl(index, 0); + BIND(LOOP); + for (int i = 0; i < fill64_per_loop; i++) { + fill64(Address(base, index, Address::times_1, i * 64), xtmp, use64byteVector); + } + addl(index, fill64_per_loop * 64); + cmpl(index, start64 * 64); + jccb(Assembler::less, LOOP); + } + for (int i = start64; i < vector64_count; i++) { fill64(base, i * 64, xtmp, use64byteVector); } @@ -8874,22 +8892,29 @@ void MacroAssembler::fill32_masked(uint shift, Register dst, int disp, } -void MacroAssembler::fill32(Register dst, int disp, XMMRegister xmm) { +void MacroAssembler::fill32(Address dst, XMMRegister xmm) { assert(MaxVectorSize >= 32, "vector length should be >= 32"); - vmovdqu(Address(dst, disp), xmm); + vmovdqu(dst, xmm); } -void MacroAssembler::fill64(Register dst, int disp, XMMRegister xmm, bool use64byteVector) { +void MacroAssembler::fill32(Register dst, int disp, XMMRegister xmm) { + fill32(Address(dst, disp), xmm); +} + +void MacroAssembler::fill64(Address dst, XMMRegister xmm, bool use64byteVector) { assert(MaxVectorSize >= 32, "vector length should be >= 32"); - BasicType type[] = {T_BYTE, T_SHORT, T_INT, T_LONG}; if (!use64byteVector) { - fill32(dst, disp, xmm); - fill32(dst, disp + 32, xmm); + fill32(dst, xmm); + fill32(dst.plus_disp(32), xmm); } else { - evmovdquq(Address(dst, disp), xmm, Assembler::AVX_512bit); + evmovdquq(dst, xmm, Assembler::AVX_512bit); } } +void MacroAssembler::fill64(Register dst, int disp, XMMRegister xmm, bool use64byteVector) { + fill64(Address(dst, disp), xmm, use64byteVector); +} + #ifdef _LP64 void MacroAssembler::generate_fill_avx3(BasicType type, Register to, Register value, Register count, Register rtmp, XMMRegister xtmp) { diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 255e6c4c97551..70ec1ffcc52f9 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1985,8 +1985,12 @@ class MacroAssembler: public Assembler { XMMRegister xmm, KRegister mask, Register length, Register temp); + void fill32(Address dst, XMMRegister xmm); + void fill32(Register dst, int disp, XMMRegister xmm); + void fill64(Address dst, XMMRegister xmm, bool use64byteVector = false); + void fill64(Register dst, int dis, XMMRegister xmm, bool use64byteVector = false); #ifdef _LP64 diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 18bc45a7c40b8..2150fbbcf718e 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -3072,7 +3072,7 @@ Node* ClearArrayNode::Identity(PhaseGVN* phase) { // Clearing a short array is faster with stores Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Already know this is a large node, do not try to ideal it - if (!IdealizeClearArrayNode || _is_large) return NULL; + if (_is_large) return NULL; const int unit = BytesPerLong; const TypeX* t = phase->type(in(2))->isa_intptr_t(); @@ -3093,6 +3093,7 @@ Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { } else if (size > 2 && Matcher::match_rule_supported_vector(Op_ClearArray, 4, T_LONG)) { return NULL; } + if (!IdealizeClearArrayNode) return NULL; Node *mem = in(1); if( phase->type(mem)==Type::TOP ) return NULL; Node *adr = in(3); diff --git a/test/hotspot/jtreg/compiler/c2/ClearArray.java b/test/hotspot/jtreg/compiler/c2/ClearArray.java new file mode 100644 index 0000000000000..55d717c31195e --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/ClearArray.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022, 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 ClearArray.java + * @bug 8284883 + * @compile ClearArray.java + * @summary ClearArray instruction overflows scratch buffer + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xbatch + * -XX:InitArrayShortSize=32768 -XX:-IdealizeClearArrayNode compiler.c2.ClearArray + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -Xbatch + * -XX:InitArrayShortSize=32768 -XX:-IdealizeClearArrayNode -XX:UseAVX=3 compiler.c2.ClearArray + */ + +package compiler.c2; + +public class ClearArray { + + static long[] STATIC; + + static void foo() { + STATIC = new long[2048 - 1]; + } + + public static void main(String[] args) { + for (int i = 0; i < 20_000; ++i) { + foo(); + } + } +}