folly: Range: outline exception throwing
authorLucian Grijincu <lucian@fb.com>
Thu, 29 Sep 2016 05:33:39 +0000 (22:33 -0700)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Thu, 29 Sep 2016 05:38:45 +0000 (22:38 -0700)
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

folly/Range.h

index 59e14bd5df84bb00b94ee975a347f879b079304f..9cacdd58877c1693c295ebb63e0c9653f3058a44 100644 (file)
@@ -145,6 +145,11 @@ struct IsCharPointer<const char*> {
   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
 
 /**
@@ -217,7 +222,7 @@ public:
   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
   Range(const std::string& str, std::string::size_type startFrom) {
     if (UNLIKELY(startFrom > str.size())) {
-      throw std::out_of_range("index out of range");
+      detail::throwOutOfRange();
     }
     b_ = str.data() + startFrom;
     e_ = str.data() + str.size();
@@ -228,7 +233,7 @@ public:
         std::string::size_type startFrom,
         std::string::size_type size) {
     if (UNLIKELY(startFrom > str.size())) {
-      throw std::out_of_range("index out of range");
+      detail::throwOutOfRange();
     }
     b_ = str.data() + startFrom;
     if (str.size() - startFrom < size) {
@@ -251,7 +256,7 @@ public:
   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
   Range(const fbstring& str, fbstring::size_type startFrom) {
     if (UNLIKELY(startFrom > str.size())) {
-      throw std::out_of_range("index out of range");
+      detail::throwOutOfRange();
     }
     b_ = str.data() + startFrom;
     e_ = str.data() + str.size();
@@ -261,7 +266,7 @@ public:
   Range(const fbstring& str, fbstring::size_type startFrom,
         fbstring::size_type size) {
     if (UNLIKELY(startFrom > str.size())) {
-      throw std::out_of_range("index out of range");
+      detail::throwOutOfRange();
     }
     b_ = str.data() + startFrom;
     if (str.size() - startFrom < size) {
@@ -426,12 +431,12 @@ public:
   }
 
   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];
   }
 
   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];
   }
 
@@ -453,21 +458,21 @@ public:
 
   void advance(size_type n) {
     if (UNLIKELY(n > size())) {
-      throw std::out_of_range("index out of range");
+      detail::throwOutOfRange();
     }
     b_ += n;
   }
 
   void subtract(size_type n) {
     if (UNLIKELY(n > size())) {
-      throw std::out_of_range("index out of range");
+      detail::throwOutOfRange();
     }
     e_ -= n;
   }
 
   Range subpiece(size_type first, size_type length = npos) const {
     if (UNLIKELY(first > size())) {
-      throw std::out_of_range("index out of range");
+      detail::throwOutOfRange();
     }
 
     return Range(b_ + first, std::min(length, size() - first));
@@ -628,7 +633,7 @@ public:
     } else if (e == e_) {
       e_ = b;
     } else {
-      throw std::out_of_range("index out of range");
+      detail::throwOutOfRange();
     }
   }