Просмотр исходного кода

AK: Convince GCC that m_outline_capacity isn't being read

Previously GCC came to the conclusion that we were reading
m_outline_capacity via ByteBuffer(ByteBuffer const&) -> grow()
-> capacity() even though that could never be the case because
m_size is 0 at that point which means we have an inline buffer
and capacity() would return inline_capacity in that case without
reading m_outline_capacity.

This makes GCC inline parts of the grow() function into the
ByteBuffer copy constructor which seems sufficient for GCC to
realize that m_outline_capacity isn't actually being read.
Gunnar Beutner 4 лет назад
Родитель
Сommit
bacb2dea70
1 измененных файлов с 22 добавлено и 17 удалено
  1. 22 17
      AK/ByteBuffer.h

+ 22 - 17
AK/ByteBuffer.h

@@ -146,7 +146,7 @@ public:
         m_size = 0;
     }
 
-    void grow(size_t new_size)
+    ALWAYS_INLINE void grow(size_t new_size)
     {
         if (new_size <= m_size)
             return;
@@ -154,19 +154,7 @@ public:
             m_size = new_size;
             return;
         }
-        u8* new_buffer;
-        auto new_capacity = kmalloc_good_size(new_size);
-        if (!is_inline()) {
-            new_buffer = (u8*)krealloc(m_outline_buffer, new_capacity);
-            VERIFY(new_buffer);
-        } else {
-            new_buffer = (u8*)kmalloc(new_capacity);
-            VERIFY(new_buffer);
-            __builtin_memcpy(new_buffer, data(), m_size);
-        }
-        m_outline_buffer = new_buffer;
-        m_outline_capacity = new_capacity;
-        m_size = new_size;
+        grow_slowpath(new_size);
     }
 
     void append(void const* data, size_t data_size)
@@ -230,12 +218,29 @@ private:
         m_size = size;
     }
 
-    bool is_inline() const { return m_size <= inline_capacity; }
-    size_t capacity() const { return is_inline() ? inline_capacity : m_outline_capacity; }
+    NEVER_INLINE void grow_slowpath(size_t new_size)
+    {
+        u8* new_buffer;
+        auto new_capacity = kmalloc_good_size(new_size);
+        if (!is_inline()) {
+            new_buffer = (u8*)krealloc(m_outline_buffer, new_capacity);
+            VERIFY(new_buffer);
+        } else {
+            new_buffer = (u8*)kmalloc(new_capacity);
+            VERIFY(new_buffer);
+            __builtin_memcpy(new_buffer, data(), m_size);
+        }
+        m_outline_buffer = new_buffer;
+        m_outline_capacity = new_capacity;
+        m_size = new_size;
+    }
+
+    ALWAYS_INLINE bool is_inline() const { return m_size <= inline_capacity; }
+    ALWAYS_INLINE size_t capacity() const { return is_inline() ? inline_capacity : m_outline_capacity; }
 
     size_t m_size { 0 };
     union {
-        u8 m_inline_buffer[inline_capacity] {};
+        u8 m_inline_buffer[inline_capacity];
         struct {
             u8* m_outline_buffer;
             size_t m_outline_capacity;