- 17 Aug, 2018 4 commits
-
-
Lewis Baker authored
Summary: Adds four template metafunctions that can be used when building generic coroutine code. - `is_awaitable<T>`, `is_awaitable_v<T>` Query whether a type can be co_awaited within a "normal" coroutine. - `is_awaiter<T>`, `is_awaiter_v<T>` Query whether a type implements the `await_ready()`, `await_suspend()` and `await_resume()` methods required for the 'Awaiter' concept. - `awaiter_type<T>`, `awaiter_type_t<T>` Query what the 'Awaiter' type is for a given 'Awaitable' type. This will be the return-type of whatever `operator co_await()` returns, if one is defined, otherwise is type of the Awaitable itself. - `await_result<T>`, `await_result_t<T>` Query what the type resulting from applying the `co_await` operator to a value of type, `T`. - Moved the existing `folly::coro::get_awaiter()` implementation from 'AwaitWrapper.h' into 'Traits.h'. Note that these traits all currently assume that the `co_await` operator appears within a coroutine that does not provide an `await_transform()` customisation point. A promise type that implements the `await_transform()` customisation point can arbitrarily change the behaviour of a `co_await` that occurs within its body. Reviewed By: andriigrynenko Differential Revision: D9382593 fbshipit-source-id: e9ddfec4a62579a4b2649c070e53e8639e7c68a1
-
Neel Goyal authored
Summary: Introduction of `folly::IOBuf::wrapIov` and the subsequent change to `WriteChainAsyncTransportWrapper` introduced a subtle change where someone sending a number of 0 length iovs would still get their WriteCallback invoked. This fixes that case and also invokes WriteCallback if no iovs are to be wrapped. Arguably, both of these are invalid uses of the API, but this at least fixes the subtleties. Reviewed By: knekritz Differential Revision: D9379661 fbshipit-source-id: 73d2f7cd1494be4ccccaa9c1fd834ae5410d6421
-
Arik Sosman authored
Summary: The API deleted here was added to plan for use in proxygen downstream client auth but we ended up using better alternatives. Given how the wangle pipeline works caller to the getter may never get things other than success (if it's error, connection is closed and pipeline won't flow to the point) without complex OpenSSL callback setup. As a result, it's very unlikely to be used in the future. Let's just remove them to avoid confusion. Reviewed By: yfeldblum Differential Revision: D9361517 fbshipit-source-id: 75d1cf71ee88a5a9ec28a151ddd4ea4aaf9506ed
-
Marshall Cline authored
Summary: This is part of "the great r-valuification of folly::Future": * This is something we should do for safety in general. * Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical). * This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.). * This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect. * The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).unwrap(...)` instead of `f.unwrap(...)`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics. Reviewed By: yfeldblum Differential Revision: D9329273 fbshipit-source-id: fbcda4310fe4d008b7c7595d320d15e3581f09c1
-
- 16 Aug, 2018 7 commits
-
-
Lewis Baker authored
Summary: Remove the `waitAsync()` method from `folly::coro::Baton` and provide an `operator co_await()` instead. This moves the method to be consistent with other folly::coro APIs that use the convention of prefixing the method with co_ when the return-value is an awaitable type. In this case it seemed better to allow `co_await baton;` rather than use the potentially confusing `co_await baton.co_wait()` method as the `co_wait` method name seemed too close to and easily confused with the `co_await` keyword. Reviewed By: andriigrynenko Differential Revision: D9308773 fbshipit-source-id: 922793a83306e5b1e5e60c69b47b98a9bdd17d8d
-
Dave Watson authored
Summary: D9197722 added new files, but did not add them to makefile.am Reviewed By: AjanthanAsogamoorthy Differential Revision: D9361032 fbshipit-source-id: f398619424969594bb9af9b76d475cb23d1a97e5
-
Yedidya Feldblum authored
Summary: [Folly] Add `noexcept` specifier to `hash_combine` and `hash_combine_generic`. Reviewed By: nbronson Differential Revision: D9346979 fbshipit-source-id: 201700019ae9fc5046deac3ed083105abe565382
-
Eric Niebler authored
Summary: Constructing an `exception_wrapper` from an `std::exception_ptr` and a reference to an exception could never throw an exception, but was not marked `noexcept`. So annotate it. Reviewed By: yfeldblum, lewissbaker Differential Revision: D9351489 fbshipit-source-id: 858299330b376360fc6420b6c901ab846d577854
-
Asier Gutierrez authored
Summary: Pull Request resolved: https://github.com/facebook/folly/pull/912 Reviewed By: Orvid Differential Revision: D9344568 Pulled By: yfeldblum fbshipit-source-id: bcafaab895454f21c3005825003916d771210d33
-
Yedidya Feldblum authored
Summary: [Folly] Let `hash_combine_generic` take hasher instances as parameters v.s. taking hasher types as template parameters. This would permit its use with non-default-constructible hasher types (if any exist). Reviewed By: nbronson Differential Revision: D9330419 fbshipit-source-id: 2fb306e16603c07812559c47e31d7a9e2edcb072
-
Marshall Cline authored
Summary: This is part of "the great r-valuification of folly::Future": * This is something we should do for safety in general. * Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical). * This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.). * This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect. * The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).unwrap(...)` instead of `f.unwrap(...)`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics. Codemod changes: * expr.unwrap(...) ==> std::move(expr).unwrap(...) // if expr is not already an xvalue * expr->unwrap(...) ==> std::move(*expr).unwrap(...) Note: operator precedence of that last step is safe - no need to parenthesize `expr`. Reason: `->` binds more tightly than unary `*`. Reviewed By: LeeHowes Differential Revision: D9350632 fbshipit-source-id: 54806eb982cf22c4c29d326d8ba894837125f291
-
- 15 Aug, 2018 5 commits
-
-
Dave Watson authored
Summary: Adds a crc32_combine function to folly (and crc32c hardware) Reviewed By: yfeldblum Differential Revision: D7687302 fbshipit-source-id: 86393c54776fa63ecfb34e9a589256e92505eeae
-
Marshall Cline authored
Summary: This is part of "the great r-valuification of folly::Future": * This is something we should do for safety in general. * Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical). * This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.). * This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect. * The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).filter(...)` instead of `f.filter(...)`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics. Reviewed By: yfeldblum Differential Revision: D9329311 fbshipit-source-id: a2640ffe8c70addee9f9ce3614281aa337acaaaf
-
Marshall Cline authored
Summary: This is part of "the great r-valuification of folly::Future": * This is something we should do for safety in general. * Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical). * This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.). * This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect. * The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).reduce(...)` instead of `f.reduce(...)`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics. Reviewed By: yfeldblum Differential Revision: D9329242 fbshipit-source-id: 4f192863e69c12484578db6f756de82b97c4427b
-
Dave Watson authored
Summary: Update the TDigest interface to accept unsorted or sorted data. If unsorted, use a custom radix sort explicitly aimed at this use case: doubles only, assume small data, so we don't use in-place and everything still fits in cache (1000-10000 items). Previously D8875766. This version does not require newer boost versions, and puts everything in the heap, so there should be no fiber overflows. Reviewed By: yfeldblum Differential Revision: D9197722 fbshipit-source-id: 10088cf14d1ff88e1072c00084e09129271e97ec
-
Yedidya Feldblum authored
Summary: [Folly] Cut config-time detection of `cplus_demangle_v3_callback` and the forward declarations and copy-pasting symbols, replacing them with `__has_include(<demangle.h>)`. Reviewed By: Orvid Differential Revision: D9287760 fbshipit-source-id: 4464ec22dd6f96cf081cda6051bebe4d41813390
-
- 14 Aug, 2018 11 commits
-
-
Gareth Chen authored
Summary: Adding an implementation of X509_get0_tbs_sigalg for pre-1.1.0 versions of OpenSSL Reviewed By: fredemmott Differential Revision: D9317612 fbshipit-source-id: b7d270a818f802d7df537cdb23e2129dfb184567
-
Marshall Cline authored
Summary: This is part of "the great r-valuification of folly::Future": * This is something we should do for safety in general. * Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical). * This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.). * This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect. * The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).unit()` instead of `f.unit()`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics. Reviewed By: yfeldblum Differential Revision: D9308405 fbshipit-source-id: 3ae0001deef1aef203454112757f8f64c47831fc
-
Marshall Cline authored
Summary: This is part of "the great r-valuification of folly::Future": * This is something we should do for safety in general. * Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical). * This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.). * This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect. * The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).filter(...)` instead of `f.filter(...)`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics. Reviewed By: yfeldblum Differential Revision: D9308741 fbshipit-source-id: 671b1b7a39f16bcc20ad9f584ed0ca8def53d21c
-
Marshall Cline authored
Summary: This is part of "the great r-valuification of folly::Future": * This is something we should do for safety in general. * Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical). * This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.). * This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect. * The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).ensure(...)` instead of `f.ensure(...)`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics. Reviewed By: yfeldblum Differential Revision: D9309465 fbshipit-source-id: dd3bcf753aa54d3c6da647b828c35a436abffecc
-
Marshall Cline authored
Summary: This is part of "the great r-valuification of folly::Future": * This is something we should do for safety in general. * Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical). * This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.). * This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect. * The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).reduce(...)` instead of `f.reduce(...)`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics. Reviewed By: yfeldblum Differential Revision: D9309840 fbshipit-source-id: 7dbb26dc5e5c7a04720c1fb903e33dfa799e8713
-
Marshall Cline authored
Summary: This is part of "the great r-valuification of folly::Future": * This is something we should do for safety in general. * Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical). * This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.). * This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect. * The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).unwrap(...)` instead of `f.unwrap(...)`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics. Reviewed By: yfeldblum Differential Revision: D9309748 fbshipit-source-id: eeda770f9e0d3462e1d4680e45d68c8355156b0c
-
Lee Howes authored
Summary: Overall plan to modify Future<T>::then to be r-value qualified and use Future<T>::thenTry or Future<T>::thenValue. The goal is to disambiguate folly::Future and to improve type and lifetime safety of Future and its methods. Diff to remove the l-value qualified version of folly::Future::then. Post on the topic of improving safety of Future: https://fb.facebook.com/groups/fbcode/permalink/1726007767436055/ Reviewed By: marshallcline Differential Revision: D9175988 fbshipit-source-id: 942ae3e1548e8538497eaa0cbde68829c3145d1d
-
Neel Goyal authored
Summary: Add utility to IOBuf to wrap iovecs and have WriteChainAsyncTransportWrapper use this. In the future, custom transports could use this method specialized handling of writev without subclassing WriteChainAsyncTransportWrapper. Reviewed By: yfeldblum Differential Revision: D9297258 fbshipit-source-id: 9afc17f2ac2c46a49ce384e7c4d8c3a82afa1eec
-
Terence Feng authored
Summary: lvalue-qualified then() has been deprecated lvalue-qualified get() has been deleted Pull Request resolved: https://github.com/facebook/folly/pull/911 Reviewed By: LeeHowes Differential Revision: D9310836 Pulled By: yfeldblum fbshipit-source-id: 662596bf5985f7ceabb2a23725d51f8e05407340
-
Orvid King authored
Summary: As per: https://github.com/facebook/folly/commit/ffbc96640b6db68a8e1b020b1048ab45b0699b23#commitcomment-30059248 Reviewed By: yfeldblum Differential Revision: D9306902 fbshipit-source-id: 79eca471bf911c6791425432f537c6f2e7f99f49
-
Oleksiy Ivanov authored
Summary: In some cases OPENSSL_IS_BORINGSSL can be defined as simple as: or in copts: -DOPENSSL_IS_BORINGSSL this causing folly to fail compilation. Pull Request resolved: https://github.com/facebook/folly/pull/909 Reviewed By: ngoyal Differential Revision: D9308739 Pulled By: yfeldblum fbshipit-source-id: 2ce6170cd97b75ad2322ac57b45824202fe34f21
-
- 13 Aug, 2018 5 commits
-
-
Lewis Baker authored
Summary: Adds an async Mutex that allows a coroutine to `co_await` acquiring the lock on a mutex. This mutex is not cancellable and does not support timeouts, but is very efficient and does not require any per-operation memory allocations (memory for tracking the list of waiting coroutines is borrowed from the awaiting coroutine frame). The Mutex class provides fair locking by implementing a FIFO queue of waiting coroutines. ie. coroutines will acquire the lock in the order that they await the lock operation. This could be relaxed in the future if needed to provide bounded wait-times but not necessarily FIFO order. Example usage: ```c++ template<typename T> class ConcurrentStack { folly::coro::Mutex mutex_; std::vector<T> values_; public: coro::Task<void> pushAsync(T value) { auto lock = co_await mutex_.scopedLockAsync(); values_.push_back(value); } coro::Task<Optional<T>> tryPopAsync() { auto lock = co_await mutex_.scopedLockAsync(); if (values_.empty()) co_return Optional<T>{}; T result = values_.back(); values_.pop_back(); co_return result; } }; ``` Reviewed By: andriigrynenko Differential Revision: D9209637 fbshipit-source-id: 4b81c8f33b9fc39781f4237d1821b0e0b2e4f3c5
-
Asier Gutierrez authored
Summary: Pull Request resolved: https://github.com/facebook/folly/pull/910 Reviewed By: simpkins Differential Revision: D9300288 Pulled By: yfeldblum fbshipit-source-id: 5724bcc2e9c6602a0e99c436b62893926281e673
-
Lewis Baker authored
Summary: Adds a fundamental thread-synchronisation primitive for coroutines that allows one or more coroutines to suspend execution until some thread signals them. This differs from the folly::fibers::Baton implementation in that it does not expose a blocking wait API, only an asynchronous wait API that must be waited-on from within a coroutine. This implementation also permits multiple coroutines concurrently waiting on the baton. Example usage: ```c++ folly::coro::Baton baton; std::string sharedValue; folly::coro::Task<void> consumer() { // Wait until the baton is posted. co_await baton.waitAsync(); // Now safe to read shared state. std::cout << sharedValue << std::cout; } void producer() { // Write to shared state sharedValue = "some result"; // Publish the value by 'posting' the baton. // This will resume the consumer if it was currently suspended. baton.post(); } ``` Reviewed By: andriigrynenko Differential Revision: D9208955 fbshipit-source-id: 07aa372b4c6b90dc0565763add716e591d312c65
-
Dan Zimmerman authored
Summary: We try to detect if you're building for a darwin version where clock_gettime doesn't have a library definition and provide our own if that's the case. However, if you build for an earlier darwin verion but then run on a newer darwin version where clock_gettime does have a definition our symbol still overrides that one, when I think it shouldn't (I'd rather use the library definition whenever possible). This is one of the exact situations why weak linkage exists (I guess at least on darwin since that's the only place I have knowledge), so let's use it here: provide our own definition if a library one doesn't exist, otherwise the strong library definition will override ours. This creates the following issue now: previous to this diff you would have a unified API (though divergent from the system one on darwin) across all versions of darwin when linking in this library. Now when running on a newer version of darwin the semantics of each clock type may change (in fact I know CLOCK_MONOTONIC diverges). Look for a follow up diff to try and patch up divergence. Reviewed By: mzlee, Orvid Differential Revision: D8781475 fbshipit-source-id: e80e9d309115b64563511935ef074c4f46da025b
-
Gennady Zlobin authored
Summary: Successfully built on Fedora, added a comment that it will work on Fedora up to 28 Reviewed By: yfeldblum Differential Revision: D9147146 fbshipit-source-id: a768eee4becadcb017547d96207d63d43ec2be57
-
- 11 Aug, 2018 8 commits
-
-
Yedidya Feldblum authored
Summary: [Folly] Replace `FOLLY_HAVE_FEATURES_H` with `__has_include`. Now that folly only targets which support `__has_include`. Reviewed By: simpkins Differential Revision: D9281991 fbshipit-source-id: 2e263681df5a980220fc133e8ac0495f229f6084
-
Yedidya Feldblum authored
Summary: [Folly] Replace `FOLLY_HAVE_MALLOC_H` with `__has_include`. Now that folly only targets which support `__has_include`. Reviewed By: Orvid Differential Revision: D9281875 fbshipit-source-id: eb895f3e034e4a4d3c9eb34fb73d47893e59f5ef
-
Yedidya Feldblum authored
Summary: [Folly] Replace `FOLLY_HAVE_LIBDWARF_DWARF_H` with `__has_include`. Now that folly only targets which support `__has_include`. Reviewed By: Orvid Differential Revision: D9281453 fbshipit-source-id: f416a6e4eb25ec31f86c705b7e9aafb1064e876a
-
Yedidya Feldblum authored
Summary: [Folly] Replace `FOLLY_HAVE_BITS_CXXCONFIG_H` with `__has_include`. Now that folly only targets which support `__has_include`. Reviewed By: Orvid Differential Revision: D9280942 fbshipit-source-id: cd843b4e903b2c96d3a40611f2274572b8b0600a
-
Yedidya Feldblum authored
Summary: [Folly] Replace `FOLLY_HAVE_LINUX_MEMBARRIER_H` with `__has_include`. Now that folly only targets which support `__has_include`. Reviewed By: Orvid Differential Revision: D9279852 fbshipit-source-id: 94c446a2d6e2662d32a7899ab470679da6da8e0e
-
Victor Zverovich authored
Summary: This fixes various include and dependency issues found when building `folly/compression/test/facebook:compression_fuzz_test.so` with modules. Reviewed By: yfeldblum Differential Revision: D9271280 fbshipit-source-id: e0ae46c2a6d95c8f4d0a66e3dc20e1d045ffc6a4
-
Matthieu Martin authored
Summary: This reverts my previous change "RequestContext: replace F14FastMap by std::unordred_map" Reviewed By: ot Differential Revision: D9280469 fbshipit-source-id: ad3f4d5f520e88ab0e0fab0506d87bab2cd10d41
-
Yedidya Feldblum authored
Summary: [Folly] Epochs for `BufferedRandomDevice`. To maintain the security property that the thread-local object is reset after fork in the child process, but in an async-signal-safe way. This approach has the downside that it makes the fast path larger by 3 instruction (`mov`, `cmp`, `jne`). Reviewed By: djwatson, ot Differential Revision: D9256536 fbshipit-source-id: dc34e1aeb75e1009610d47fe4ef7030a4a0e2a90
-