diff --git a/libcxx/benchmarks/map.bench.cpp b/libcxx/benchmarks/map.bench.cpp --- a/libcxx/benchmarks/map.bench.cpp +++ b/libcxx/benchmarks/map.bench.cpp @@ -111,17 +111,15 @@ using Base::Base; void run(benchmark::State& State) const { - auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1); - auto& Map = Data.Maps.front(); - while (State.KeepRunningBatch(MapSize)) { -#ifndef VALIDATE - benchmark::DoNotOptimize( - std::map(Map.begin(), Map.end())); -#else - std::map M{Map.begin(), Map.end()}; - if (M != Map) - State.SkipWithError("Map copy not identical"); -#endif + auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + while (State.KeepRunningBatch(MapSize * Data.Maps.size())) { + for (auto& Map : Data.Maps) { + std::map M(Map.begin(), Map.end()); + benchmark::DoNotOptimize(M); + } + State.PauseTiming(); + Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + State.ResumeTiming(); } } @@ -132,17 +130,15 @@ using Base::Base; void run(benchmark::State& State) const { - auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1); - auto& Map = Data.Maps.front(); - while (State.KeepRunningBatch(MapSize)) { -#ifndef VALIDATE - std::map M(Map); - benchmark::DoNotOptimize(M); -#else - std::map M(Map); - if (M != Map) - State.SkipWithError("Map copy not identical"); -#endif + auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + while (State.KeepRunningBatch(MapSize * Data.Maps.size())) { + for (auto const& Map : Data.Maps) { + std::map M(Map); + benchmark::DoNotOptimize(M); + } + State.PauseTiming(); + Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + State.ResumeTiming(); } } @@ -168,6 +164,47 @@ std::string name() const { return "BM_ConstructorMove" + baseName(); } }; +struct CopyAssignment : Base { + using Base::Base; + + void run(benchmark::State& State) const { + auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + while (State.KeepRunningBatch(MapSize * Data.Maps.size())) { + for (auto const& Map : Data.Maps) { + std::map M; + M = Map; + benchmark::DoNotOptimize(M); + } + State.PauseTiming(); + Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + State.ResumeTiming(); + } + } + + std::string name() const { return "BM_CopyAssignment" + baseName(); } +}; + +struct CopyAssignmentPrepopulated : Base { + using Base::Base; + + void run(benchmark::State& State) const { + auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + auto Init = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + while (State.KeepRunningBatch(MapSize * Data.Maps.size())) { + for (std::size_t i = 0; i != Data.Maps.size(); ++i) { + Init.Maps[i] = Data.Maps[i]; + benchmark::DoNotOptimize(Init.Maps[i]); + } + State.PauseTiming(); + Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + Init = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000); + State.ResumeTiming(); + } + } + + std::string name() const { return "BM_CopyAssignmentPrepopulated" + baseName(); } +}; + //*******************************************************************| // Capacity | //*******************************************************************| @@ -1006,6 +1043,8 @@ makeCartesianProductBenchmark(MapSize); makeCartesianProductBenchmark(MapSize); makeCartesianProductBenchmark(MapSize); + makeCartesianProductBenchmark(MapSize); + makeCartesianProductBenchmark(MapSize); // Capacity makeCartesianProductBenchmark(MapSize); diff --git a/libcxx/include/__tree b/libcxx/include/__tree --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -1116,7 +1116,7 @@ _LIBCPP_HIDE_FROM_ABI explicit __tree(const allocator_type& __a); _LIBCPP_HIDE_FROM_ABI __tree(const value_compare& __comp, const allocator_type& __a); _LIBCPP_HIDE_FROM_ABI __tree(const __tree& __t); - _LIBCPP_HIDE_FROM_ABI __tree& operator=(const __tree& __t); + _LIBCPP_HIDE_FROM_ABI __tree& operator=(const __tree& __t) = delete; // use __assign_unique or __assign_multi instead template _LIBCPP_HIDE_FROM_ABI void __assign_unique(_ForwardIterator __first, _ForwardIterator __last); template @@ -1542,6 +1542,8 @@ template friend class _LIBCPP_TEMPLATE_VIS map; template friend class _LIBCPP_TEMPLATE_VIS multimap; + template friend class _LIBCPP_TEMPLATE_VIS set; + template friend class _LIBCPP_TEMPLATE_VIS multiset; }; template @@ -1617,19 +1619,6 @@ return static_cast<__node_pointer>(_VSTD::__tree_leaf(__cache->__left_)); } -template -__tree<_Tp, _Compare, _Allocator>& -__tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t) -{ - if (this != _VSTD::addressof(__t)) - { - value_comp() = __t.value_comp(); - __copy_assign_alloc(__t); - __assign_multi(__t.begin(), __t.end()); - } - return *this; -} - template template void @@ -1649,8 +1638,8 @@ __cache.__advance(); } } - for (; __first != __last; ++__first) - __insert_unique(*__first); + for (const_iterator __e = end(); __first != __last; ++__first) + __insert_unique(__e, *__first); } template @@ -1673,8 +1662,8 @@ __cache.__advance(); } } - for (; __first != __last; ++__first) - __insert_multi(_NodeTypes::__get_value(*__first)); + for (const_iterator __e = end(); __first != __last; ++__first) + __insert_multi(__e, _NodeTypes::__get_value(*__first)); } template diff --git a/libcxx/include/map b/libcxx/include/map --- a/libcxx/include/map +++ b/libcxx/include/map @@ -735,8 +735,6 @@ class multimap; template class __map_const_iterator; -#ifndef _LIBCPP_CXX03_LANG - template struct _LIBCPP_STANDALONE_DEBUG __value_type { @@ -817,33 +815,6 @@ __value_type(__value_type&&) = delete; }; -#else - -template -struct __value_type -{ - typedef _Key key_type; - typedef _Tp mapped_type; - typedef pair value_type; - -private: - value_type __cc_; - -public: - _LIBCPP_INLINE_VISIBILITY - value_type& __get_value() { return __cc_; } - _LIBCPP_INLINE_VISIBILITY - const value_type& __get_value() const { return __cc_; } - -private: - __value_type(); - __value_type(__value_type const&); - __value_type& operator=(__value_type const&); - ~__value_type(); -}; - -#endif // _LIBCPP_CXX03_LANG - template struct __extract_key_value_types; @@ -1095,16 +1066,11 @@ _LIBCPP_INLINE_VISIBILITY map& operator=(const map& __m) { -#ifndef _LIBCPP_CXX03_LANG - __tree_ = __m.__tree_; -#else if (this != _VSTD::addressof(__m)) { - __tree_.clear(); __tree_.value_comp() = __m.__tree_.value_comp(); __tree_.__copy_assign_alloc(__m.__tree_); - insert(__m.begin(), __m.end()); + __tree_.__assign_unique(__m.begin(), __m.end()); } -#endif return *this; } @@ -1895,16 +1861,11 @@ _LIBCPP_INLINE_VISIBILITY multimap& operator=(const multimap& __m) { -#ifndef _LIBCPP_CXX03_LANG - __tree_ = __m.__tree_; -#else if (this != _VSTD::addressof(__m)) { - __tree_.clear(); __tree_.value_comp() = __m.__tree_.value_comp(); __tree_.__copy_assign_alloc(__m.__tree_); - insert(__m.begin(), __m.end()); + __tree_.__assign_multi(__m.begin(), __m.end()); } -#endif return *this; } diff --git a/libcxx/include/set b/libcxx/include/set --- a/libcxx/include/set +++ b/libcxx/include/set @@ -610,7 +610,11 @@ _LIBCPP_INLINE_VISIBILITY set& operator=(const set& __s) { - __tree_ = __s.__tree_; + if (this != std::addressof(__s)) { + __tree_.value_comp() = __s.__tree_.value_comp(); + __tree_.__copy_assign_alloc(__s.__tree_); + __tree_.__assign_unique(__s.begin(), __s.end()); + } return *this; } @@ -1148,7 +1152,11 @@ _LIBCPP_INLINE_VISIBILITY multiset& operator=(const multiset& __s) { - __tree_ = __s.__tree_; + if (this != std::addressof(__s)) { + __tree_.value_comp() = __s.__tree_.value_comp(); + __tree_.__copy_assign_alloc(__s.__tree_); + __tree_.__assign_multi(__s.begin(), __s.end()); + } return *this; }