代码拉取完成,页面将自动刷新
Subject: Backport JDK-8320308 C2 compilation crashes in LibraryCallKit::inline_unsafe_access
---
src/hotspot/share/opto/library_call.cpp | 7 +-
.../TestUnsafeArrayAccessWithNullBase.java | 113 ++++++++++++++++++
2 files changed, 117 insertions(+), 3 deletions(-)
create mode 100644 test/hotspot/jtreg/compiler/parsing/TestUnsafeArrayAccessWithNullBase.java
diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp
index af2ea6095..3ef0098c4 100644
--- a/src/hotspot/share/opto/library_call.cpp
+++ b/src/hotspot/share/opto/library_call.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -2004,7 +2004,7 @@ LibraryCallKit::classify_unsafe_addr(Node* &base, Node* &offset, BasicType type)
if (base_type == nullptr) {
// Unknown type.
return Type::AnyPtr;
- } else if (base_type == TypePtr::NULL_PTR) {
+ } else if (_gvn.type(base->uncast()) == TypePtr::NULL_PTR) {
// Since this is a null+long form, we have to switch to a rawptr.
base = _gvn.transform(new CastX2PNode(offset));
offset = MakeConX(0);
@@ -2322,8 +2322,9 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c
SafePointNode* old_map = clone_map();
Node* adr = make_unsafe_address(base, offset, type, kind == Relaxed);
+ assert(!stopped(), "Inlining of unsafe access failed: address construction stopped unexpectedly");
- if (_gvn.type(base)->isa_ptr() == TypePtr::NULL_PTR) {
+ if (_gvn.type(base->uncast())->isa_ptr() == TypePtr::NULL_PTR) {
if (type != T_OBJECT) {
decorators |= IN_NATIVE; // off-heap primitive access
} else {
diff --git a/test/hotspot/jtreg/compiler/parsing/TestUnsafeArrayAccessWithNullBase.java b/test/hotspot/jtreg/compiler/parsing/TestUnsafeArrayAccessWithNullBase.java
new file mode 100644
index 000000000..28eb4f3c1
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/parsing/TestUnsafeArrayAccessWithNullBase.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2024, 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 8320308
+ * @summary Unsafe::getShortUnaligned with base null hidden behind CheckCastPP nodes
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @run main/othervm -Xbatch -XX:CompileCommand=quiet -XX:TypeProfileLevel=222
+ * -XX:+IgnoreUnrecognizedVMOptions -XX:+AlwaysIncrementalInline
+ * -XX:CompileCommand=compileonly,compiler.parsing.TestUnsafeArrayAccessWithNullBase::test*
+ * -XX:-TieredCompilation compiler.parsing.TestUnsafeArrayAccessWithNullBase
+ * @run main compiler.parsing.TestUnsafeArrayAccessWithNullBase
+ */
+
+package compiler.parsing;
+
+import java.lang.reflect.*;
+import jdk.internal.misc.Unsafe;
+
+public class TestUnsafeArrayAccessWithNullBase {
+
+ /*
+ Trigger bug when handling Unsafe.getShortUnaligned with null checks and inlined methods.
+ The bug appears when the method is incrementally inlined and optimized based on the argument profile information.
+
+ Warmup Phase: By warming up with non-null values, the argument profile for the helper methods records non-null types.
+ - insert CheckCastPP: speculative=byte[int:>=0] for return of getSmall/getLarge
+ - insert CheckCastPP: speculative=byte[int:>=0] for argument `Object array` in helperSmall/helperLarge
+ Trigger Phase: Calling test causes LibraryCallKit::inline_unsafe_access(..) for Unsafe::getShortUnaligned to fail:
+ Reason: UNSAFE.getShortUnaligned(array, offset) is called with array=null,
+ but ConP null is now hidden by two CheckCastPP with speculative=byte[int:>=0] in the graph
+ */
+
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
+ private static final Object byteArray = new byte[1_050_000];
+
+ public static Object getLarge(boolean useNull) {
+ return useNull ? null : byteArray;
+ }
+
+ public static Object getSmall(boolean useNull) {
+ return useNull ? null : new byte[10];
+ }
+
+ // use a helper to delay inlining of UNSAFE.getShortUnaligned
+ public static int helperLarge(Object array, boolean run) {
+ // offset >= os::vm_page_size(): LibraryCallKit::classify_unsafe_addr returns Type::AnyPtr
+ return run ? UNSAFE.getShortUnaligned(array, 1_049_000) : 0; // after warmup CheckCastPP: speculative=byte[int:>=0]
+ }
+
+ public static int accessLargeArray(boolean useNull, boolean run) {
+ Object array = getLarge(useNull); // after warmup CheckCastPP: speculative=byte[int:>=0]
+ // getLarge() ensures null is only visible after helperLarge was (incrementally) inlined
+ return helperLarge(array, run);
+ }
+
+ // use a helper to delay inlining of UNSAFE.getShortUnaligned
+ // warmup adds argument profile information for array: CheckCastPP with type non null
+ public static int helperSmall(Object array, boolean run) {
+ // 0 <= offset < os::vm_page_size(): LibraryCallKit::classify_unsafe_addr returns Type::OopPtr
+ return run ? UNSAFE.getShortUnaligned(array, 1) : 0; // after warmup CheckCastPP: speculative=byte[int:>=0]
+ }
+
+ public static int accessSmallArray(boolean useNull, boolean run) {
+ Object array = getSmall(useNull); // after warmup CheckCastPP: speculative=byte[int:>=0]
+ return helperSmall(array, run);
+ }
+
+ public static int test1(boolean run) {
+ return accessLargeArray(true, run);
+ }
+
+ public static int test2(boolean run) {
+ return accessSmallArray(true, run);
+ }
+
+ public static void main(String[] args) {
+ // Warmup to collect speculative types
+ for (int i = 0; i < 10_000; i++) {
+ accessLargeArray(false, true);
+ accessSmallArray(false, true);
+ }
+
+ // Trigger Compilation
+ for (int i = 0; i < 10_000; ++i) {
+ test1(false);
+ test2(false);
+ }
+ }
+}
--
2.33.0
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。