Commit 4eb1b242 authored by Nathan Bronson's avatar Nathan Bronson Committed by Facebook GitHub Bot

handle MSVC debug iterator tracking in F14 fallback

Summary:
MSVC's maintains an intrusive linked list of iterators for
debugging purposes in some build configurations, which means that
F14MapFallback's hacky conversion from unordered_map::local_iterator to
unordered_map::iterator doesn't work.  Fortunately, on that platform
local_iterator and iterator are the same type, so no hack is needed.

Reviewed By: Orvid

Differential Revision: D22776318

fbshipit-source-id: 80283c4c451afffe522e55e47cd94971126a6fa6
parent a055d929
...@@ -211,7 +211,7 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> { ...@@ -211,7 +211,7 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> {
return std::make_pair(it, false); return std::make_pair(it, false);
} }
auto rv = Super::emplace(std::forward<decltype(inner)>(inner)...); auto rv = Super::emplace(std::forward<decltype(inner)>(inner)...);
FOLLY_SAFE_CHECK( FOLLY_SAFE_DCHECK(
rv.second, "post-find emplace should always insert"); rv.second, "post-find emplace should always insert");
return rv; return rv;
} else { } else {
...@@ -289,7 +289,6 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> { ...@@ -289,7 +289,6 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> {
template <typename K2> template <typename K2>
struct BottomKeyEqual { struct BottomKeyEqual {
[[noreturn]] bool operator()(K2 const&, K2 const&) const { [[noreturn]] bool operator()(K2 const&, K2 const&) const {
FOLLY_SAFE_CHECK(false, "bucket should not invoke key equality");
assume_unreachable(); assume_unreachable();
} }
}; };
...@@ -379,19 +378,33 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> { ...@@ -379,19 +378,33 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> {
} }
private: private:
template <typename Iter, typename LocalIter>
static std::
enable_if_t<std::is_constructible<Iter, LocalIter const&>::value, Iter>
fromLocal(LocalIter const& src, int = 0) {
return Iter(src);
}
template <typename Iter, typename LocalIter>
static std::
enable_if_t<!std::is_constructible<Iter, LocalIter const&>::value, Iter>
fromLocal(LocalIter const& src) {
Iter dst;
static_assert(sizeof(dst) <= sizeof(src), "");
std::memcpy(std::addressof(dst), std::addressof(src), sizeof(dst));
FOLLY_SAFE_CHECK(
std::addressof(*src) == std::addressof(*dst),
"ABI-assuming local_iterator to iterator conversion failed");
return dst;
}
template <typename Iter, typename Self, typename K2> template <typename Iter, typename Self, typename K2>
static Iter findImpl(Self& self, K2 const& key) { static Iter findImpl(Self& self, K2 const& key) {
auto optLocalIt = findLocal(self, key); auto optLocalIt = findLocal(self, key);
if (!optLocalIt) { if (!optLocalIt) {
return self.end(); return self.end();
} else { } else {
Iter it; return fromLocal<Iter>(*optLocalIt);
static_assert(sizeof(it) <= sizeof(*optLocalIt), "");
std::memcpy(&it, &*optLocalIt, sizeof(it));
FOLLY_SAFE_CHECK(
std::addressof(**optLocalIt) == std::addressof(*it),
"ABI-assuming local_iterator to iterator conversion failed");
return it;
} }
} }
......
...@@ -116,7 +116,7 @@ class F14BasicSet ...@@ -116,7 +116,7 @@ class F14BasicSet
return std::make_pair(it, false); return std::make_pair(it, false);
} }
auto rv = Super::emplace(std::forward<decltype(key)>(key)); auto rv = Super::emplace(std::forward<decltype(key)>(key));
FOLLY_SAFE_CHECK( FOLLY_SAFE_DCHECK(
rv.second, "post-find emplace should always insert"); rv.second, "post-find emplace should always insert");
return rv; return rv;
} else { } else {
...@@ -150,11 +150,30 @@ class F14BasicSet ...@@ -150,11 +150,30 @@ class F14BasicSet
template <typename K> template <typename K>
struct BottomKeyEqual { struct BottomKeyEqual {
[[noreturn]] bool operator()(K const&, K const&) const { [[noreturn]] bool operator()(K const&, K const&) const {
FOLLY_SAFE_CHECK(false, "bucket should not invoke key equality");
assume_unreachable(); assume_unreachable();
} }
}; };
template <typename Iter, typename LocalIter>
static std::
enable_if_t<std::is_constructible<Iter, LocalIter const&>::value, Iter>
fromLocal(LocalIter const& src, int = 0) {
return Iter(src);
}
template <typename Iter, typename LocalIter>
static std::
enable_if_t<!std::is_constructible<Iter, LocalIter const&>::value, Iter>
fromLocal(LocalIter const& src) {
Iter dst;
static_assert(sizeof(dst) <= sizeof(src), "");
std::memcpy(std::addressof(dst), std::addressof(src), sizeof(dst));
FOLLY_SAFE_CHECK(
std::addressof(*src) == std::addressof(*dst),
"ABI-assuming local_iterator to iterator conversion failed");
return dst;
}
template <typename Iter, typename Self, typename K> template <typename Iter, typename Self, typename K>
static Iter findImpl(Self& self, K const& key) { static Iter findImpl(Self& self, K const& key) {
if (self.empty()) { if (self.empty()) {
...@@ -171,13 +190,7 @@ class F14BasicSet ...@@ -171,13 +190,7 @@ class F14BasicSet
auto e = self.end(slot); auto e = self.end(slot);
while (b != e) { while (b != e) {
if (self.key_eq()(key, *b)) { if (self.key_eq()(key, *b)) {
Iter it; return fromLocal<Iter>(b);
static_assert(sizeof(it) <= sizeof(b), "");
std::memcpy(&it, &b, sizeof(it));
FOLLY_SAFE_CHECK(
std::addressof(*b) == std::addressof(*it),
"ABI-assuming local_iterator to iterator conversion failed");
return it;
} }
++b; ++b;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment