--- old/src/share/vm/runtime/atomic.hpp 2017-08-16 01:47:28.145395241 -0400 +++ new/src/share/vm/runtime/atomic.hpp 2017-08-16 01:47:28.029389292 -0400 @@ -123,15 +123,26 @@ U compare_value, cmpxchg_memory_order order = memory_order_conservative); + // Performs atomic compare of *dest and NULL, and replaces *dest + // with exchange_value if the comparison succeeded. Returns true if + // the comparison succeeded and the exchange occurred. This is + // often used as part of lazy initialization, as a lock-free + // alternative to the Double-Checked Locking Pattern. template - inline static bool conditional_store_ptr(T* value, D* volatile* dest, - cmpxchg_memory_order order = memory_order_conservative); + inline static bool replace_if_null(T* value, D* volatile* dest, + cmpxchg_memory_order order = memory_order_conservative); - inline static intptr_t cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, cmpxchg_memory_order order = memory_order_conservative) { + inline static intptr_t cmpxchg_ptr(intptr_t exchange_value, + volatile intptr_t* dest, + intptr_t compare_value, + cmpxchg_memory_order order = memory_order_conservative) { return cmpxchg(exchange_value, dest, compare_value, order); } - inline static void* cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value, cmpxchg_memory_order order = memory_order_conservative) { + inline static void* cmpxchg_ptr(void* exchange_value, + volatile void* dest, + void* compare_value, + cmpxchg_memory_order order = memory_order_conservative) { return cmpxchg(exchange_value, reinterpret_cast(dest), compare_value, @@ -156,14 +167,14 @@ // of 1, 4, and 8 are required. The class is a function object that // must be default constructable, with these requirements: // - // - dest is of type D*. - // - exchange_value and compare_value are of type D. + // - dest is of type T*. + // - exchange_value and compare_value are of type T. // - order is of type cmpxchg_memory_order. - // - platform_cmpxchg is an object of type PlatformCmpxchg. + // - platform_cmpxchg is an object of type PlatformCmpxchg. // // Then - // platform_cmpxchg()(exchange_value, dest, compare_value, order) - // must be a valid expression, returning a result convertible to D. + // platform_cmpxchg(exchange_value, dest, compare_value, order) + // must be a valid expression, returning a result convertible to T. // // A default definition is provided, which declares a function template // T operator()(T, T volatile*, T, cmpxchg_memory_order) const @@ -178,24 +189,26 @@ // The generic arguments passed to PlatformCmpxchg need to be // translated to the appropriate type for the helper function, the // helper invoked on the translated arguments, and the result - // translated back. - template - static T cmpxchg_using_stub(StubFn stub_fn, - T exchange_value, - T volatile* dest, - T compare_value); - - // Support platforms that do not provide RMW byte-level atomic access - // To use, derive PlatformCmpxchg<1> from this class. - // Can't be private: C++03 11.4/2; fixed in C++11. -public: + // translated back. Type is the parameter / return type of the + // helper function. + template + static T cmpxchg_using_helper(Fn fn, + T exchange_value, + T volatile* dest, + T compare_value); + + // Support platforms that do not provide Read-Modify-Write + // byte-level atomic access. To use, derive PlatformCmpxchg<1> from + // this class. +public: // Temporary, can't be private: C++03 11.4/2. Fixed by C++11. struct CmpxchgByteUsingInt; private: }; template struct Atomic::IsPointerConvertible : AllStatic { - // Use the "sizeof trick" to test for convertibility. + // Determine whether From* is implicitly convertible to To*, using + // the "sizeof trick". typedef char yes; typedef char (&no)[2]; @@ -206,11 +219,11 @@ static const bool value = (sizeof(yes) == sizeof(test(test_value))); }; -// Define class before including platform file, which may specialize +// Define the class before including platform file, which may specialize // the operator definition. No generic definition of specializations // of the operator template are provided, nor are there any generic -// specializations of the class. That all needs to be provided by the -// platform file. +// specializations of the class. The platform file is responsible for +// providing those. template struct Atomic::PlatformCmpxchg VALUE_OBJ_CLASS_SPEC { template @@ -220,9 +233,9 @@ cmpxchg_memory_order order) const; }; -// Define class before including platform file, which may use this as -// a base class, requiring it be complete. The operator template -// definition is defined later. +// Define the class before including platform file, which may use this +// as a base class, requiring it be complete. The definition is later +// in this file, near the other definitions related to cmpxchg. struct Atomic::CmpxchgByteUsingInt VALUE_OBJ_CLASS_SPEC { template T operator()(T exchange_value, @@ -263,8 +276,11 @@ } template -inline bool Atomic::conditional_store_ptr(T* value, D* volatile* dest, - cmpxchg_memory_order order) { +inline bool Atomic::replace_if_null(T* value, D* volatile* dest, + cmpxchg_memory_order order) { + // Presently using a trivial implementation in terms of cmpxchg. + // Consider adding platform support, to permit the use of compiler + // intrinsics like gcc's __sync_bool_compare_and_swap. D* expected_null = NULL; return expected_null == cmpxchg(value, dest, expected_null, order); } @@ -310,9 +326,8 @@ // Allow derived to base conversion, and adding cv-qualifiers. D* new_value = exchange_value; // Don't care what the CV qualifiers for compare_value are, - // but we need to match D when calling platform support. - typedef typename RemoveCV::type U_nocv; - D* old_value = const_cast(compare_value); + // but we need to match D* when calling platform support. + D* old_value = const_cast(compare_value); return PlatformCmpxchg()(new_value, dest, old_value, order); } }; @@ -343,16 +358,16 @@ } }; -template -inline T Atomic::cmpxchg_using_stub(StubFn stub_fn, - T exchange_value, - T volatile* dest, - T compare_value) { - STATIC_ASSERT(sizeof(StubType) == sizeof(T)); +template +inline T Atomic::cmpxchg_using_helper(Fn fn, + T exchange_value, + T volatile* dest, + T compare_value) { + STATIC_ASSERT(sizeof(Type) == sizeof(T)); return IntegerTypes::cast( - stub_fn(IntegerTypes::cast(exchange_value), - reinterpret_cast(dest), - IntegerTypes::cast(compare_value))); + fn(IntegerTypes::cast(exchange_value), + reinterpret_cast(dest), + IntegerTypes::cast(compare_value))); } template