Add mechanizm for caching local and peer addresses in AsyncSSLSocket.
[folly.git] / folly / Bits.cpp
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <folly/Bits.h>
18
19 #include <folly/CpuId.h>
20 #include <folly/Portability.h>
21
22 // None of this is necessary if we're compiling for a target that supports
23 // popcnt, which includes MSVC
24 #if !defined(__POPCNT__) && !defined(_MSC_VER)
25 namespace {
26
27 int popcount_builtin(unsigned int x) {
28   return __builtin_popcount(x);
29 }
30
31 int popcountll_builtin(unsigned long long x) {
32   return __builtin_popcountll(x);
33 }
34
35 #if FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS)
36
37 // Strictly speaking, these versions of popcount are usable without ifunc
38 // support. However, we would have to check, via CpuId, if the processor
39 // implements the popcnt instruction first, which is what we use ifunc for.
40 int popcount_inst(unsigned int x) {
41   int n;
42   asm ("popcntl %1, %0" : "=r" (n) : "r" (x));
43   return n;
44 }
45
46 int popcountll_inst(unsigned long long x) {
47   unsigned long long n;
48   asm ("popcntq %1, %0" : "=r" (n) : "r" (x));
49   return n;
50 }
51
52 typedef decltype(popcount_builtin) Type_popcount;
53 typedef decltype(popcountll_builtin) Type_popcountll;
54
55 // This function is called on startup to resolve folly::detail::popcount
56 extern "C" Type_popcount* folly_popcount_ifunc() {
57   return folly::CpuId().popcnt() ?  popcount_inst : popcount_builtin;
58 }
59
60 // This function is called on startup to resolve folly::detail::popcountll
61 extern "C" Type_popcountll* folly_popcountll_ifunc() {
62   return folly::CpuId().popcnt() ?  popcountll_inst : popcountll_builtin;
63 }
64
65 #endif  // FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS)
66
67 }  // namespace
68
69 namespace folly {
70 namespace detail {
71
72 // Call folly_popcount_ifunc on startup to resolve to either popcount_inst
73 // or popcount_builtin
74 int popcount(unsigned int x)
75 #if FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS)
76   __attribute__((__ifunc__("folly_popcount_ifunc")));
77 #else
78 {  return popcount_builtin(x); }
79 #endif
80
81 // Call folly_popcount_ifunc on startup to resolve to either popcountll_inst
82 // or popcountll_builtin
83 int popcountll(unsigned long long x)
84 #if FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS)
85   __attribute__((__ifunc__("folly_popcountll_ifunc")));
86 #else
87 {  return popcountll_builtin(x); }
88 #endif
89
90 }  // namespace detail
91 }  // namespace folly
92
93 #endif  /* !__POPCNT__ */