Commit d6c0ba01 authored by Lucian Grijincu's avatar Lucian Grijincu Committed by Facebook Github Bot

folly: Range: outline exception throwing

Summary:
Here's some godbolt: 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

Reviewed By: ot

Differential Revision: D3940968

fbshipit-source-id: b47a41e7cdd863fcef099ff3c21860b2979ee6e8
parent 998f6331
...@@ -145,6 +145,11 @@ struct IsCharPointer<const char*> { ...@@ -145,6 +145,11 @@ struct IsCharPointer<const char*> {
typedef int type; typedef int type;
}; };
// Prevent it from being inlined to reduce instruction bloat.
FOLLY_NOINLINE inline void throwOutOfRange() {
throw std::out_of_range("index out of range");
}
} // namespace detail } // namespace detail
/** /**
...@@ -217,7 +222,7 @@ public: ...@@ -217,7 +222,7 @@ public:
template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
Range(const std::string& str, std::string::size_type startFrom) { Range(const std::string& str, std::string::size_type startFrom) {
if (UNLIKELY(startFrom > str.size())) { if (UNLIKELY(startFrom > str.size())) {
throw std::out_of_range("index out of range"); detail::throwOutOfRange();
} }
b_ = str.data() + startFrom; b_ = str.data() + startFrom;
e_ = str.data() + str.size(); e_ = str.data() + str.size();
...@@ -228,7 +233,7 @@ public: ...@@ -228,7 +233,7 @@ public:
std::string::size_type startFrom, std::string::size_type startFrom,
std::string::size_type size) { std::string::size_type size) {
if (UNLIKELY(startFrom > str.size())) { if (UNLIKELY(startFrom > str.size())) {
throw std::out_of_range("index out of range"); detail::throwOutOfRange();
} }
b_ = str.data() + startFrom; b_ = str.data() + startFrom;
if (str.size() - startFrom < size) { if (str.size() - startFrom < size) {
...@@ -251,7 +256,7 @@ public: ...@@ -251,7 +256,7 @@ public:
template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
Range(const fbstring& str, fbstring::size_type startFrom) { Range(const fbstring& str, fbstring::size_type startFrom) {
if (UNLIKELY(startFrom > str.size())) { if (UNLIKELY(startFrom > str.size())) {
throw std::out_of_range("index out of range"); detail::throwOutOfRange();
} }
b_ = str.data() + startFrom; b_ = str.data() + startFrom;
e_ = str.data() + str.size(); e_ = str.data() + str.size();
...@@ -261,7 +266,7 @@ public: ...@@ -261,7 +266,7 @@ public:
Range(const fbstring& str, fbstring::size_type startFrom, Range(const fbstring& str, fbstring::size_type startFrom,
fbstring::size_type size) { fbstring::size_type size) {
if (UNLIKELY(startFrom > str.size())) { if (UNLIKELY(startFrom > str.size())) {
throw std::out_of_range("index out of range"); detail::throwOutOfRange();
} }
b_ = str.data() + startFrom; b_ = str.data() + startFrom;
if (str.size() - startFrom < size) { if (str.size() - startFrom < size) {
...@@ -426,12 +431,12 @@ public: ...@@ -426,12 +431,12 @@ public:
} }
value_type& at(size_t i) { value_type& at(size_t i) {
if (i >= size()) throw std::out_of_range("index out of range"); if (i >= size()) detail::throwOutOfRange();
return b_[i]; return b_[i];
} }
const value_type& at(size_t i) const { const value_type& at(size_t i) const {
if (i >= size()) throw std::out_of_range("index out of range"); if (i >= size()) detail::throwOutOfRange();
return b_[i]; return b_[i];
} }
...@@ -453,21 +458,21 @@ public: ...@@ -453,21 +458,21 @@ public:
void advance(size_type n) { void advance(size_type n) {
if (UNLIKELY(n > size())) { if (UNLIKELY(n > size())) {
throw std::out_of_range("index out of range"); detail::throwOutOfRange();
} }
b_ += n; b_ += n;
} }
void subtract(size_type n) { void subtract(size_type n) {
if (UNLIKELY(n > size())) { if (UNLIKELY(n > size())) {
throw std::out_of_range("index out of range"); detail::throwOutOfRange();
} }
e_ -= n; e_ -= n;
} }
Range subpiece(size_type first, size_type length = npos) const { Range subpiece(size_type first, size_type length = npos) const {
if (UNLIKELY(first > size())) { if (UNLIKELY(first > size())) {
throw std::out_of_range("index out of range"); detail::throwOutOfRange();
} }
return Range(b_ + first, std::min(length, size() - first)); return Range(b_ + first, std::min(length, size() - first));
...@@ -628,7 +633,7 @@ public: ...@@ -628,7 +633,7 @@ public:
} else if (e == e_) { } else if (e == e_) {
e_ = b; e_ = b;
} else { } else {
throw std::out_of_range("index out of range"); detail::throwOutOfRange();
} }
} }
......
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