Summary:
A ton of these functions are tiny and should be inlined. `throw std::out_of_range("bla")` generates quite a lot of code.
See godbolt from {
D3940968}: https://godbolt.org/g/9K36Km
advanceNoInline(S):
movq %rdi, %rax
sarq $32, %rax
cmpl %eax, %edi
jg .L20
leal 1(%rdi), %eax
ret
.L20:
subq $8, %rsp
call S::outOfRange() [clone .isra.0]
vs previous implementation
advance(S):
movq %rdi, %rdx
sarq $32, %rdx
cmpl %edx, %edi
jg .L14
leal 1(%rdi), %eax
ret
.L14:
pushq %rbp
pushq %rbx
movl $16, %edi
subq $8, %rsp
call __cxa_allocate_exception
movl $.LC0, %esi
movq %rax, %rdi
movq %rax, %rbx
call std::out_of_range::out_of_range(char const*)
movl std::out_of_range::~out_of_range(), %edx
movl typeinfo for std::out_of_range, %esi
movq %rbx, %rdi
call __cxa_throw
movq %rax, %rbp
movq %rbx, %rdi
call __cxa_free_exception
movq %rbp, %rdi
call _Unwind_Resume
This pattern is in the standard library as well:
```
reference
at(size_type __n)
{
if (__n >= _Nm)
std::__throw_out_of_range(__N("array::at"));
return _M_instance[__n];
}
```
https://github.com/gcc-mirror/gcc/blob/
edd716b6b1caa1a5cb320a8cd7f626f30198e098/libstdc%2B%2B-v3/include/tr1/array#L138
Reviewed By: yfeldblum
Differential Revision:
D3947075
fbshipit-source-id:
6e174c725791762a533a534c8482ea9576460b86
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
+#include <folly/portability/BitsFunctexcept.h>
TValue& get(const TKey& key) {
auto it = find(key);
if (it == end()) {
TValue& get(const TKey& key) {
auto it = find(key);
if (it == end()) {
- throw std::out_of_range("Key does not exist");
+ std::__throw_out_of_range("Key does not exist");
const TValue& getWithoutPromotion(const TKey& key) const {
auto it = findWithoutPromotion(key);
if (it == end()) {
const TValue& getWithoutPromotion(const TKey& key) const {
auto it = findWithoutPromotion(key);
if (it == end()) {
- throw std::out_of_range("Key does not exist");
+ std::__throw_out_of_range("Key does not exist");
#include <folly/Likely.h>
#include <folly/Malloc.h>
#include <folly/Traits.h>
#include <folly/Likely.h>
#include <folly/Malloc.h>
#include <folly/Traits.h>
+#include <folly/portability/BitsFunctexcept.h>
#include <boost/operators.hpp>
#include <boost/operators.hpp>
}
const_reference at(size_type n) const {
if (UNLIKELY(n >= size())) {
}
const_reference at(size_type n) const {
if (UNLIKELY(n >= size())) {
- throw std::out_of_range("fbvector: index is greater than size.");
+ std::__throw_out_of_range("fbvector: index is greater than size.");
* limitations under the License.
*/
* limitations under the License.
*/
-#include <folly/dynamic.h>
+#include <folly/dynamic.h>
+#include <folly/portability/BitsFunctexcept.h>
throw TypeError("int64", idx.type());
}
if (idx < 0 || idx >= parray->size()) {
throw TypeError("int64", idx.type());
}
if (idx < 0 || idx >= parray->size()) {
- throw std::out_of_range("out of range in dynamic array");
+ std::__throw_out_of_range("out of range in dynamic array");
}
return (*parray)[idx.asInt()];
} else if (auto* pobject = get_nothrow<ObjectImpl>()) {
}
return (*parray)[idx.asInt()];
} else if (auto* pobject = get_nothrow<ObjectImpl>()) {
auto result = readWhile(keepReading);
// skip over the terminator character
if (isAtEnd()) {
auto result = readWhile(keepReading);
// skip over the terminator character
if (isAtEnd()) {
- throw std::out_of_range("terminator not found");
+ std::__throw_out_of_range("terminator not found");
#include <memory>
#include <folly/Bits.h>
#include <memory>
#include <folly/Bits.h>
-#include <folly/io/IOBuf.h>
-#include <folly/io/IOBufQueue.h>
#include <folly/Likely.h>
#include <folly/Memory.h>
#include <folly/Portability.h>
#include <folly/Range.h>
#include <folly/Likely.h>
#include <folly/Memory.h>
#include <folly/Portability.h>
#include <folly/Range.h>
+#include <folly/io/IOBuf.h>
+#include <folly/io/IOBufQueue.h>
+#include <folly/portability/BitsFunctexcept.h>
/**
* Cursor class for fast iteration over IOBuf chains.
/**
* Cursor class for fast iteration over IOBuf chains.
void clone(std::unique_ptr<folly::IOBuf>& buf, size_t len) {
if (UNLIKELY(cloneAtMost(buf, len) != len)) {
void clone(std::unique_ptr<folly::IOBuf>& buf, size_t len) {
if (UNLIKELY(cloneAtMost(buf, len) != len)) {
- throw std::out_of_range("underflow");
+ std::__throw_out_of_range("underflow");
}
}
void clone(folly::IOBuf& buf, size_t len) {
if (UNLIKELY(cloneAtMost(buf, len) != len)) {
}
}
void clone(folly::IOBuf& buf, size_t len) {
if (UNLIKELY(cloneAtMost(buf, len) != len)) {
- throw std::out_of_range("underflow");
+ std::__throw_out_of_range("underflow");
}
if (otherBuf == other.buffer_) {
}
if (otherBuf == other.buffer_) {
- throw std::out_of_range("wrap-around");
+ std::__throw_out_of_range("wrap-around");
}
len += offset_;
} else {
if (offset_ < other.offset_) {
}
len += offset_;
} else {
if (offset_ < other.offset_) {
- throw std::out_of_range("underflow");
+ std::__throw_out_of_range("underflow");
}
len += offset_ - other.offset_;
}
len += offset_ - other.offset_;
len += curBuf->length();
curBuf = curBuf->next();
if (curBuf == buf || curBuf == buffer_) {
len += curBuf->length();
curBuf = curBuf->next();
if (curBuf == buf || curBuf == buffer_) {
- throw std::out_of_range("wrap-around");
+ std::__throw_out_of_range("wrap-around");
for (size_t available; (available = length()) < len; ) {
str->append(reinterpret_cast<const char*>(data()), available);
if (UNLIKELY(!tryAdvanceBuffer())) {
for (size_t available; (available = length()) < len; ) {
str->append(reinterpret_cast<const char*>(data()), available);
if (UNLIKELY(!tryAdvanceBuffer())) {
- throw std::out_of_range("string underflow");
+ std::__throw_out_of_range("string underflow");
void pullSlow(void* buf, size_t len) {
if (UNLIKELY(pullAtMostSlow(buf, len) != len)) {
void pullSlow(void* buf, size_t len) {
if (UNLIKELY(pullAtMostSlow(buf, len) != len)) {
- throw std::out_of_range("underflow");
+ std::__throw_out_of_range("underflow");
void skipSlow(size_t len) {
if (UNLIKELY(skipAtMostSlow(len) != len)) {
void skipSlow(size_t len) {
if (UNLIKELY(skipAtMostSlow(len) != len)) {
- throw std::out_of_range("underflow");
+ std::__throw_out_of_range("underflow");
void push(const uint8_t* buf, size_t len) {
Derived* d = static_cast<Derived*>(this);
if (d->pushAtMost(buf, len) != len) {
void push(const uint8_t* buf, size_t len) {
Derived* d = static_cast<Derived*>(this);
if (d->pushAtMost(buf, len) != len) {
- throw std::out_of_range("overflow");
+ std::__throw_out_of_range("overflow");
}
}
void push(ByteRange buf) {
if (this->pushAtMost(buf) != buf.size()) {
}
}
void push(ByteRange buf) {
if (this->pushAtMost(buf) != buf.size()) {
- throw std::out_of_range("overflow");
+ std::__throw_out_of_range("overflow");
*/
void push(Cursor cursor, size_t len) {
if (this->pushAtMost(cursor, len) != len) {
*/
void push(Cursor cursor, size_t len) {
if (this->pushAtMost(cursor, len) != len) {
- throw std::out_of_range("overflow");
+ std::__throw_out_of_range("overflow");
// Waste the rest of the current buffer and allocate a new one.
// Don't make it too small, either.
if (growth_ == 0) {
// Waste the rest of the current buffer and allocate a new one.
// Don't make it too small, either.
if (growth_ == 0) {
- throw std::out_of_range("can't grow buffer chain");
+ std::__throw_out_of_range("can't grow buffer chain");
}
n = std::max(n, growth_);
}
n = std::max(n, growth_);
#include <folly/Malloc.h>
#include <folly/Portability.h>
#include <folly/SmallLocks.h>
#include <folly/Malloc.h>
#include <folly/Portability.h>
#include <folly/SmallLocks.h>
+#include <folly/portability/BitsFunctexcept.h>
#include <folly/portability/Constexpr.h>
#include <folly/portability/Malloc.h>
#include <folly/portability/TypeTraits.h>
#include <folly/portability/Constexpr.h>
#include <folly/portability/Malloc.h>
#include <folly/portability/TypeTraits.h>
reference at(size_type i) {
if (i >= size()) {
reference at(size_type i) {
if (i >= size()) {
- throw std::out_of_range("index out of range");
+ std::__throw_out_of_range("index out of range");
}
return (*this)[i];
}
const_reference at(size_type i) const {
if (i >= size()) {
}
return (*this)[i];
}
const_reference at(size_type i) const {
if (i >= size()) {
- throw std::out_of_range("index out of range");
+ std::__throw_out_of_range("index out of range");
#include <vector>
#include <boost/operators.hpp>
#include <vector>
#include <boost/operators.hpp>
+#include <folly/portability/BitsFunctexcept.h>
if (it != end()) {
return it->second;
}
if (it != end()) {
return it->second;
}
- throw std::out_of_range("sorted_vector_map::at");
+ std::__throw_out_of_range("sorted_vector_map::at");
}
const mapped_type& at(const key_type& key) const {
}
const mapped_type& at(const key_type& key) const {
if (it != end()) {
return it->second;
}
if (it != end()) {
return it->second;
}
- throw std::out_of_range("sorted_vector_map::at");
+ std::__throw_out_of_range("sorted_vector_map::at");
}
size_type count(const key_type& key) const {
}
size_type count(const key_type& key) const {