diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index ad0a720c211..03c49a9bab9 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -2782,13 +2782,17 @@ bool LibraryCallKit::inline_unsafe_flat_access(bool is_store, AccessKind kind) { value = new_value; } - assert(value_type->inline_klass() == value_klass, "value is of type %s while valueType is %s", value_type->inline_klass()->name()->as_utf8(), value_klass->name()->as_utf8()); + assert(value_type == TypePtr::NULL_PTR || value_type->inline_klass() == value_klass, + "value is of type %s while value klass is %s", value_type->inline_klass()->name()->as_utf8(), value_klass->name()->as_utf8()); if (layout == LayoutKind::REFERENCE) { const TypePtr* ptr_type = (decorators & C2_MISMATCHED) != 0 ? TypeRawPtr::BOTTOM : _gvn.type(ptr)->is_ptr(); access_store_at(base, ptr, ptr_type, value, value_type, T_OBJECT, decorators); } else { bool atomic = LayoutKindHelper::is_atomic_flat(layout); bool null_free = !LayoutKindHelper::is_nullable_flat(layout); + if (null_free) { + null_check(value); + } value->as_InlineType()->store_flat(this, base, ptr, atomic, immutable_memory, null_free, decorators); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java index 299230f0b98..d9a6e3e87fe 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java @@ -149,6 +149,7 @@ public class TestIntrinsics { public TestIntrinsics() { test24_vt = MyValue1.createWithFieldsInline(rI, rL); + test31_vt = MyValue1.createDefaultInline(); super(); } @@ -658,6 +659,7 @@ public class TestIntrinsics { Asserts.assertEQ(v.v1, res); } + @NullRestricted MyValue1 test31_vt; private static final long TEST31_VT_OFFSET; private static final boolean TEST31_VT_FLATTENED; @@ -837,6 +839,54 @@ public class TestIntrinsics { Asserts.assertEQ(vt, test31_vt); } + // Test put intrinsic with null + @Test + @IR(failOn = {CALL_UNSAFE}) + public void test39(MyValue1 val) { + if (TEST31_VT_FLATTENED) { + U.putFlatValue(this, TEST31_VT_OFFSET, TEST31_VT_LAYOUT, MyValue1.class, val); + } else { + U.putReference(this, TEST31_VT_OFFSET, null); + } + } + + @Run(test = "test39") + public void test39_verifier() { + test31_vt = MyValue1.createDefaultInline(); + try { + test39(null); + if (TEST31_VT_FLATTENED) { + throw new RuntimeException("No NullPointerException thrown"); + } + } catch (NullPointerException npe) { + // Expected + } + } + + // Same as test39 but with a constant null + @Test + @IR(failOn = {CALL_UNSAFE}) + public void test39Constant() { + if (TEST31_VT_FLATTENED) { + U.putFlatValue(this, TEST31_VT_OFFSET, TEST31_VT_LAYOUT, MyValue1.class, null); + } else { + U.putReference(this, TEST31_VT_OFFSET, null); + } + } + + @Run(test = "test39Constant") + public void test39Constant_verifier() { + test31_vt = MyValue1.createDefaultInline(); + try { + test39Constant(); + if (TEST31_VT_FLATTENED) { + throw new RuntimeException("No NullPointerException thrown"); + } + } catch (NullPointerException npe) { + // Expected + } + } + // Test value class array creation via reflection @Test public Object[] test40(Class componentType, int len) {