diff --git a/src/hotspot/share/opto/vector.cpp b/src/hotspot/share/opto/vector.cpp index f9fa02317bc..8e0f6f5bf43 100644 --- a/src/hotspot/share/opto/vector.cpp +++ b/src/hotspot/share/opto/vector.cpp @@ -29,6 +29,7 @@ #include "opto/phaseX.hpp" #include "opto/rootnode.hpp" #include "opto/vector.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" static bool is_vector_mask(ciKlass* klass) { @@ -455,11 +456,12 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) { gvn.record_for_igvn(local_mem); BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); C2OptAccess access(gvn, ctrl, local_mem, decorators, T_OBJECT, obj, addr); + vec_field_ld = bs->load_at(access, Type::get_const_basic_type(T_OBJECT)); // For proper aliasing, attach concrete payload type. ciKlass* payload_klass = ciTypeArrayKlass::make(bt); const Type* payload_type = TypeAryPtr::make_from_klass(payload_klass)->cast_to_ptr_type(TypePtr::NotNull); - vec_field_ld = bs->load_at(access, payload_type); + vec_field_ld = gvn.transform(new CheckCastPPNode(ctrl, vec_field_ld, payload_type, ConstraintCastNode::DependencyType::NonFloatingNarrowing)); } Node* adr = kit.array_element_address(vec_field_ld, gvn.intcon(0), bt); diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index 96b717fe56c..d04eda60b81 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -174,7 +174,10 @@ Node* GraphKit::unbox_vector(Node* v, const TypeInstPtr* vbox_type, BasicType el } assert(check_vbox(vbox_type), ""); const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_type->instance_klass())); - Node* unbox = gvn().transform(new VectorUnboxNode(C, vt, v, merged_memory())); + Node* ctrl = control(); + Node* mem = reset_memory(); + set_all_memory(mem); + Node* unbox = gvn().transform(new VectorUnboxNode(C, vt, ctrl, v, mem)); if (gvn().type(unbox)->isa_vect() == nullptr) { assert(gvn().type(unbox) == Type::TOP, "sanity"); return nullptr; // not a vector diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 73181bce256..d013bbc25d6 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -2156,11 +2156,10 @@ class VectorBoxAllocateNode : public CallStaticJavaNode { // vector value. This is a macro node expanded during vector optimization // phase. class VectorUnboxNode : public VectorNode { - protected: - uint size_of() const { return sizeof(*this); } - public: - VectorUnboxNode(Compile* C, const TypeVect* vec_type, Node* obj, Node* mem) +public: + VectorUnboxNode(Compile* C, const TypeVect* vec_type, Node* ctrl, Node* obj, Node* mem) : VectorNode(mem, obj, vec_type) { + init_req(0, ctrl); init_class_id(Class_VectorUnbox); init_flags(Flag_is_macro); C->add_macro_node(this); @@ -2171,6 +2170,10 @@ class VectorUnboxNode : public VectorNode { Node* mem() const { return in(1); } virtual Node* Identity(PhaseGVN* phase); Node* Ideal(PhaseGVN* phase, bool can_reshape); + +private: + uint size_of() const { return sizeof(*this); } + bool depends_only_on_test_impl() const { return false; } }; // Lane-wise right rotation of the first input by the second input. diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestTypeUnsafeLoad.java b/test/hotspot/jtreg/compiler/vectorapi/TestTypeUnsafeLoad.java new file mode 100644 index 00000000000..8d4a580efb8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestTypeUnsafeLoad.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2026, 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. + */ +package compiler.vectorapi; + +import jdk.incubator.vector.ByteVector; +import jdk.incubator.vector.VectorOperators; +import jdk.incubator.vector.VectorShuffle; + +/* + * @test + * @bug 8387012 + * @summary Expansion of a VectorUnboxNode should not create a type-unsafe load. + * @modules jdk.incubator.vector + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xbatch -XX:-TieredCompilation + * -XX:+StressGCM -XX:+StressIGVN -XX:+StressCCP ${test.main.class} + */ +public class TestTypeUnsafeLoad { + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(); + } + } + + public static ByteVector test() { + var v0 = ByteVector.broadcast(ByteVector.SPECIES_128, (byte) 0); + var v2 = v0.rearrange(VectorShuffle.makeUnzip(ByteVector.SPECIES_128, 1)); + var v3 = v0.lanewise(VectorOperators.MIN, v2); + var v5 = v3.lanewise(VectorOperators.MAX, v0); + return v5; + } +}