From 3f3dcb708d2e8326c96c42566fa765a878e68bf6 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Wed, 4 Feb 2026 08:41:38 +0000 Subject: [PATCH] 8376810: Make Atomic default constructor non-explicit Reviewed-by: kbarrett, aboldtch, azafari, tschatzl --- src/hotspot/share/runtime/atomic.hpp | 14 ++-- test/hotspot/gtest/runtime/test_atomic.cpp | 87 +++++++++++++++++++++- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/runtime/atomic.hpp b/src/hotspot/share/runtime/atomic.hpp index f708e9c18ca..894e04eec57 100644 --- a/src/hotspot/share/runtime/atomic.hpp +++ b/src/hotspot/share/runtime/atomic.hpp @@ -58,9 +58,10 @@ // ValueType -> T // // special functions: -// explicit constructor(T) +// constexpr constructor() // See (2) below +// explicit constexpr constructor(T) // noncopyable -// destructor +// destructor // Trivial // // static member functions: // value_offset_in_bytes() -> int // constexpr @@ -343,7 +344,8 @@ class AtomicImpl::Atomic : public SupportsArithmetic { public: - explicit constexpr Atomic(T value = 0) : SupportsArithmetic(value) {} + constexpr Atomic() : Atomic(0) {} + explicit constexpr Atomic(T value) : SupportsArithmetic(value) {} NONCOPYABLE(Atomic); @@ -383,7 +385,8 @@ class AtomicImpl::Atomic : public CommonCore { public: - explicit constexpr Atomic(T value = 0) : CommonCore(value) {} + constexpr Atomic() : Atomic(0) {} + explicit constexpr Atomic(T value) : CommonCore(value) {} NONCOPYABLE(Atomic); @@ -399,7 +402,8 @@ class AtomicImpl::Atomic : public SupportsArithmetic { public: - explicit constexpr Atomic(T value = nullptr) : SupportsArithmetic(value) {} + constexpr Atomic() : Atomic(nullptr) {} + explicit constexpr Atomic(T value) : SupportsArithmetic(value) {} NONCOPYABLE(Atomic); diff --git a/test/hotspot/gtest/runtime/test_atomic.cpp b/test/hotspot/gtest/runtime/test_atomic.cpp index 753dde0ca57..80e67ef0bf9 100644 --- a/test/hotspot/gtest/runtime/test_atomic.cpp +++ b/test/hotspot/gtest/runtime/test_atomic.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 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 @@ -22,15 +22,100 @@ * */ +#include "cppstdlib/new.hpp" #include "cppstdlib/type_traits.hpp" #include "metaprogramming/primitiveConversions.hpp" #include "runtime/atomic.hpp" +#include "runtime/os.hpp" #include "unittest.hpp" // These tests of Atomic only verify functionality. They don't verify // atomicity. +template +struct AtomicInitializationTestSupport { + struct Holder { + Atomic _explicitly_initialized; + Atomic _default_initialized; + Atomic _value_initialized; + + Holder() + : _explicitly_initialized(T()), + /* _default_initialized */ + _value_initialized{} + {} + }; + + struct HolderNoConstructor { + Atomic _default_initialized; + }; + + void test() { + T t = T(); + + { + Holder h; + + EXPECT_EQ(t, h._explicitly_initialized.load_relaxed()); + EXPECT_EQ(t, h._default_initialized.load_relaxed()); + EXPECT_EQ(t, h._value_initialized.load_relaxed()); + } + + { + Holder h{}; + + EXPECT_EQ(t, h._explicitly_initialized.load_relaxed()); + EXPECT_EQ(t, h._default_initialized.load_relaxed()); + EXPECT_EQ(t, h._value_initialized.load_relaxed()); + } + + { + alignas(Holder) char mem[sizeof(Holder)]; + memset(mem, 0xFF, sizeof(Holder)); + Holder* h = new (mem) Holder(); + + EXPECT_EQ(t, h->_explicitly_initialized.load_relaxed()); + EXPECT_EQ(t, h->_default_initialized.load_relaxed()); + EXPECT_EQ(t, h->_value_initialized.load_relaxed()); + } + + // No-constructor variant + + { + HolderNoConstructor h; + + EXPECT_EQ(t, h._default_initialized.load_relaxed()); + } + + { + HolderNoConstructor h{}; + + EXPECT_EQ(t, h._default_initialized.load_relaxed()); + } + + { + alignas(HolderNoConstructor) char mem[sizeof(HolderNoConstructor)]; + memset(mem, 0xFF, sizeof(HolderNoConstructor)); + HolderNoConstructor* h = new (mem) HolderNoConstructor(); + + EXPECT_EQ(t, h->_default_initialized.load_relaxed()); + } + } +}; + +TEST_VM(AtomicInitializationTest, byte) { + AtomicInitializationTestSupport().test(); +} + +TEST_VM(AtomicInitializationTest, integer) { + AtomicInitializationTestSupport().test(); +} + +TEST_VM(AtomicInitializationTest, pointer) { + AtomicInitializationTestSupport().test(); +} + template struct AtomicIntegerArithmeticTestSupport { Atomic _test_value;