Use natural alignment for prevector #17530

pull laanwj wants to merge 2 commits into bitcoin:master from laanwj:2019_11_prevector changing 2 files +0 −4
  1. laanwj commented at 9:17 am on November 20, 2019: member

    #pragma pack(1) prevents aligning the struct and its members to their required alignment. This can result in code that performs non-aligned reads and writes to integers and pointers, which is problematic on some architectures.

    It also triggers UBsan — see #17156 (comment) and #17510.

    So remove the pragmas.

  2. Use natural alignment for prevector
    `#pragma pack(1)` prevents aligning the struct and its members to
    their required alignment. This can result in code that performs non-aligned reads and writes
    to integers and pointers, which is problematic on some architectures.
    
    It also triggers UBsan —
    see https://github.com/bitcoin/bitcoin/pull/17156#issuecomment-543123631 and #17510.
    7c6dd71664
  3. laanwj added the label Utils/log/libs on Nov 20, 2019
  4. test: Remove ubsan alignment suppressions
    This can be done now that prevector is properly aligned.
    5432306cbb
  5. laanwj force-pushed on Nov 20, 2019
  6. MarcoFalke commented at 12:42 pm on November 20, 2019: member
    @jamesob Would be nice to see IBD performance on this?
  7. practicalswift commented at 3:08 pm on November 20, 2019: contributor

    Concept ACK: thanks for tackling this!

    Would be nice to see IBD performance numbers.

    Very glad to see that float-divide-by-zero (-fsanitize=undefined) and unsigned-integer-overflow (-fsanitize=integer) are the only suppressions left for -fsanitize=integer,undefined after the merge of this PR.

    We can get rid of the float-divide-by-zero (-fsanitize=undefined) suppressions if PR #17208 is merged too. Fans of the sanitizers: please consider reviewing :)

  8. fanquake requested review from sipa on Nov 20, 2019
  9. DrahtBot commented at 3:12 pm on November 20, 2019: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #17208 (Make all tests pass UBSan without using any UBSan suppressions by practicalswift)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  10. jamesob commented at 3:38 pm on November 20, 2019: member

    @jamesob Would be nice to see IBD performance on this?

    On it!

  11. practicalswift commented at 10:22 am on December 3, 2019: contributor
    @jamesob Any news on the IBD performance? It would be really nice to see if you have the time :)
  12. laanwj commented at 10:33 am on December 3, 2019: member
    I think this is the correct thing to do no matter the performance result, but still it’d be nice to see.
  13. practicalswift commented at 10:42 am on December 3, 2019: contributor
    @laanwj Agree totally. I really look forward to seeing this merged: this alignment issue creates a lot of sanitiser noise (or signal depending how you see it…) for me when doing my continuous fuzzing of Bitcoin Core :)
  14. practicalswift commented at 10:31 am on December 6, 2019: contributor
    ACK 5432306cbb3e06fe2c8b18a60b9767a16f018d4f – diff looks correct
  15. practicalswift commented at 9:44 pm on December 9, 2019: contributor
    People interested in getting rid of the two UBSan suppressions needed after the merge of this PR might want to review PR #17208 (“Make all tests pass UBSan without using any UBSan suppressions”) too :)
  16. laanwj commented at 4:04 am on December 10, 2019: member

    Wait, does this introduce new needed suppression? Oh you mean the other, remaining ones

    TBH it seems that there’s completely no interest in this.

  17. sipa commented at 4:43 am on December 10, 2019: member
    What is the sizeof(CScript) on x86_64 before and after this change?
  18. laanwj commented at 5:06 am on December 10, 2019: member
    before: 32 after: 40
  19. laanwj commented at 5:27 am on December 10, 2019: member

    Couldn’t fix that by reshuffling fields either, e.g. the usual suggestion of putting big fields first

    0    union direct_or_indirect {
    1        char direct[sizeof(T) * N];
    2        struct {
    3            char* indirect;
    4            size_type capacity;
    5        };
    6    } _union = {};
    7    size_type _size = 0;
    

    … a prevector<28, unsigned char> is still 40 bytes

  20. sipa commented at 5:46 am on December 10, 2019: member
    See also #17060, which makes a bigger prevector layout change (avoiding the memory increase without pragma pack).
  21. laanwj commented at 5:49 am on December 10, 2019: member

    That PR changes the layout, but it looks like it relies just as much on pragma pack(1) there.

    sizeof(Coin) before: 48 sizeof(Coin) after: 56

  22. ajtowns commented at 6:03 am on December 10, 2019: member

    This seems like it does the right thing to me fwiw:

     0--- a/src/prevector.h
     1+++ b/src/prevector.h
     2@@ -15,7 +15,6 @@
     3 #include <type_traits>
     4 #include <utility>
     5 
     6-#pragma pack(push, 1)
     7 /** Implements a drop-in replacement for std::vector<T> which stores up to N
     8  *  elements directly (without heap allocation). The types Size and Diff are
     9  *  used to store element counts, and can be any unsigned + signed type.
    10@@ -45,6 +44,9 @@ public:
    11     typedef value_type* pointer;
    12     typedef const value_type* const_pointer;
    13 
    14+    static_assert(N % alignof(Size) == 0, "Must have preallocation as a multiple of size");
    15+    static_assert(alignof(char*) % alignof(Size) == 0, "Must have Size be aligned whenever char* would be aligned");
    16+
    17     class iterator {
    18         T* ptr;
    19     public:
    20@@ -147,14 +149,23 @@ public:
    21     };
    22 
    23 private:
    24-    size_type _size = 0;
    25+
    26+#pragma pack(push,1)
    27+    // we don't want padding added here, we will ensure indirect is
    28+    // correctly aligned manually, which will in turn ensure capacity
    29+    // is aligned.
    30     union direct_or_indirect {
    31         char direct[sizeof(T) * N];
    32         struct {
    33-            size_type capacity;
    34             char* indirect;
    35+            size_type capacity;
    36         };
    37-    } _union = {};
    38+    };
    39+#pragma pack(pop)
    40+
    41+    alignas(alignof(char*)) direct_or_indirect _union = {};
    42+    size_type _size = 0;
    43+private:
    44 
    45     T* direct_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.direct) + pos; }
    46     const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
    47@@ -523,6 +534,5 @@ public:
    48         return item_ptr(0);
    49     }
    50 };
    51-#pragma pack(pop)
    
  23. laanwj commented at 6:16 am on December 10, 2019: member
    Will leave this to you @ajtowns
  24. laanwj closed this on Dec 10, 2019

  25. practicalswift commented at 7:27 am on December 10, 2019: contributor
    @ajtowns Would you mind opening a PR with that suggested change? It would be nice to get this fixed :)
  26. ajtowns commented at 8:21 am on December 10, 2019: member
    The saga continues in #17708
  27. laanwj referenced this in commit 2bdc476d4d on Feb 12, 2020
  28. sidhujag referenced this in commit 804070d470 on Feb 18, 2020
  29. sidhujag referenced this in commit e8c51acce8 on Nov 10, 2020
  30. pravblockc referenced this in commit 58f011243c on Sep 22, 2021
  31. pravblockc referenced this in commit 56a75722c9 on Sep 23, 2021
  32. kittywhiskers referenced this in commit dd0657d899 on Oct 12, 2021
  33. MarcoFalke locked this on Dec 16, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-10-04 22:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me