From ea3909acd117cab97c6c0b496f98f9a4a3a22be4 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 24 Apr 2024 19:06:46 +0000 Subject: [PATCH] 8331054: C2 MergeStores: assert failed: unexpected basic type after JDK-8318446 and JDK-8329555 Reviewed-by: thartmann, kvn --- src/hotspot/share/opto/memnode.cpp | 17 ++++-- .../jtreg/compiler/c2/TestMergeStores.java | 58 ++++++++++++++++++- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index dea4640b9d1..4eae4a49dbb 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2972,8 +2972,12 @@ StoreNode* MergePrimitiveArrayStores::run() { // Only merge stores on arrays, and the stores must have the same size as the elements. const TypeAryPtr* aryptr_t = _store->adr_type()->isa_aryptr(); - if (aryptr_t == nullptr || - type2aelembytes(aryptr_t->elem()->array_element_basic_type()) != _store->memory_size()) { + if (aryptr_t == nullptr) { + return nullptr; + } + BasicType bt = aryptr_t->elem()->array_element_basic_type(); + if (!is_java_primitive(bt) || + type2aelembytes(bt) != _store->memory_size()) { return nullptr; } @@ -3019,8 +3023,13 @@ bool MergePrimitiveArrayStores::is_compatible_store(const StoreNode* other_store // Check that the size of the stores, and the array elements are all the same. const TypeAryPtr* aryptr_t1 = _store->adr_type()->is_aryptr(); const TypeAryPtr* aryptr_t2 = other_store->adr_type()->is_aryptr(); - int size1 = type2aelembytes(aryptr_t1->elem()->array_element_basic_type()); - int size2 = type2aelembytes(aryptr_t2->elem()->array_element_basic_type()); + BasicType aryptr_bt1 = aryptr_t1->elem()->array_element_basic_type(); + BasicType aryptr_bt2 = aryptr_t2->elem()->array_element_basic_type(); + if (!is_java_primitive(aryptr_bt1) || !is_java_primitive(aryptr_bt2)) { + return false; + } + int size1 = type2aelembytes(aryptr_bt1); + int size2 = type2aelembytes(aryptr_bt2); if (size1 != size2 || size1 != _store->memory_size() || _store->memory_size() != other_store->memory_size()) { diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java index 0af46b56a56..2f662a1ed26 100644 --- a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java @@ -33,7 +33,7 @@ import java.util.Random; /* * @test - * @bug 8318446 + * @bug 8318446 8331054 * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / @@ -42,7 +42,7 @@ import java.util.Random; /* * @test - * @bug 8318446 + * @bug 8318446 8331054 * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / @@ -183,6 +183,10 @@ public class TestMergeStores { // +-----+ +-------------------+ // First use something in range, and after warmup randomize going outside the range. // Consequence: all RangeChecks stay in the final compilation. + + testGroups.put("test600", new HashMap()); + testGroups.get("test600").put("test600R", (_,i) -> { return test600R(aB.clone(), aI.clone(), i); }); + testGroups.get("test600").put("test600a", (_,i) -> { return test600a(aB.clone(), aI.clone(), i); }); } @Warmup(100) @@ -215,7 +219,8 @@ public class TestMergeStores { "test400a", "test500a", "test501a", - "test502a"}) + "test502a", + "test600a"}) public void runTests(RunInfo info) { // Repeat many times, so that we also have multiple iterations for post-warmup to potentially recompile int iters = info.isWarmUp() ? 1_000 : 50_000; @@ -1244,4 +1249,51 @@ public class TestMergeStores { } catch (ArrayIndexOutOfBoundsException _) {} return new Object[]{ a, new int[]{ idx } }; } + + @DontCompile + static Object[] test600R(byte[] aB, int[] aI, int i) { + Object a = null; + long base = 0; + if (i % 2 == 0) { + a = aB; + base = UNSAFE.ARRAY_BYTE_BASE_OFFSET; + } else { + a = aI; + base = UNSAFE.ARRAY_INT_BASE_OFFSET; + } + UNSAFE.putByte(a, base + 0, (byte)0xbe); + UNSAFE.putByte(a, base + 1, (byte)0xba); + UNSAFE.putByte(a, base + 2, (byte)0xad); + UNSAFE.putByte(a, base + 3, (byte)0xba); + UNSAFE.putByte(a, base + 4, (byte)0xef); + UNSAFE.putByte(a, base + 5, (byte)0xbe); + UNSAFE.putByte(a, base + 6, (byte)0xad); + UNSAFE.putByte(a, base + 7, (byte)0xde); + return new Object[]{ aB, aI }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8"}) // note: bottom type + static Object[] test600a(byte[] aB, int[] aI, int i) { + Object a = null; + long base = 0; + if (i % 2 == 0) { + a = aB; + base = UNSAFE.ARRAY_BYTE_BASE_OFFSET; + } else { + a = aI; + base = UNSAFE.ARRAY_INT_BASE_OFFSET; + } + // array a is an aryptr, but its element type is unknown, i.e. bottom. + UNSAFE.putByte(a, base + 0, (byte)0xbe); + UNSAFE.putByte(a, base + 1, (byte)0xba); + UNSAFE.putByte(a, base + 2, (byte)0xad); + UNSAFE.putByte(a, base + 3, (byte)0xba); + UNSAFE.putByte(a, base + 4, (byte)0xef); + UNSAFE.putByte(a, base + 5, (byte)0xbe); + UNSAFE.putByte(a, base + 6, (byte)0xad); + UNSAFE.putByte(a, base + 7, (byte)0xde); + return new Object[]{ aB, aI }; + } + }