Skip to content

[libc][malloc] Align blocks to max_align_t. #100279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 24, 2024

Conversation

mysterymath
Copy link
Contributor

@mysterymath mysterymath commented Jul 23, 2024

Since there are two offsets from block start to usable area, this ensures that the usable area is maximally aligned, so long as the offset type size is no less than half the max alignment. This is true on at least typical 32-bit and 64-bit targets.

Previously, there was a roughly 50-50 chance a given block's usable area would be misaligned for a malloc on a 32-bit system. The half that were misaligned would require at least one block of additional padding, costing 12 bytes. With this change, the only cost is 0-4 bytes at the beginning of the heap to reach an initial 8-byte alignment.

See #98096

Since there are two offsets from block start to usable area, this
ensures that the usable area is maximally aligned, so long as the offset
type size is no less than half the max alignment. This is true on at
least typical 32-bit and 64-bit targets.

Previously, there was a roughly 50-50 chance a given block's usable area
would be misaligned for a malloc on a 32-bit system. The half that were
misaligned would require at least one block of additional padding,
costing 12 bytes. With this change, the only cost is up to 4 bytes at
the beginning of the heap to reach an 8-byte alignment.
@llvmbot
Copy link
Member

llvmbot commented Jul 23, 2024

@llvm/pr-subscribers-libc

Author: Daniel Thornburgh (mysterymath)

Changes

Since there are two offsets from block start to usable area, this ensures that the usable area is maximally aligned, so long as the offset type size is no less than half the max alignment. This is true on at least typical 32-bit and 64-bit targets.

Previously, there was a roughly 50-50 chance a given block's usable area would be misaligned for a malloc on a 32-bit system. The half that were misaligned would require at least one block of additional padding, costing 12 bytes. With this change, the only cost is 0-4 bytes at the beginning of the heap to reach an initial 8-byte alignment.


Full diff: https://github.com/llvm/llvm-project/pull/100279.diff

1 Files Affected:

  • (modified) libc/src/__support/block.h (+6-3)
diff --git a/libc/src/__support/block.h b/libc/src/__support/block.h
index af3ce181f1c99..86cb4bd7ad582 100644
--- a/libc/src/__support/block.h
+++ b/libc/src/__support/block.h
@@ -102,9 +102,12 @@ using cpp::optional;
 ///                       types can address more memory, but consume greater
 ///                       overhead.
 /// @tparam   kAlign      Sets the overall alignment for blocks. Minimum is
-///                       `alignof(OffsetType)` (the default). Larger values
-///                       cause greater overhead.
-template <typename OffsetType = uintptr_t, size_t kAlign = alignof(OffsetType)>
+///                       `alignof(OffsetType)`, but the default is max_align_t,
+///                       since the usable space will then already be
+///                       aligned to max_align_t if the size of OffsetType is no
+///                       less than half of max_align_t. Larger values cause
+///                       greater overhead.
+template <typename OffsetType = uintptr_t, size_t kAlign = alignof(max_align_t)>
 class Block {
   // Masks for the contents of the next_ field.
   static constexpr size_t USED_MASK = 1 << 0;

@mysterymath mysterymath merged commit f9cf539 into llvm:main Jul 24, 2024
8 checks passed
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
Summary:
Since there are two offsets from block start to usable area, this
ensures that the usable area is maximally aligned, so long as the offset
type size is no less than half the max alignment. This is true on at
least typical 32-bit and 64-bit targets.

Previously, there was a roughly 50-50 chance a given block's usable area
would be misaligned for a malloc on a 32-bit system. The half that were
misaligned would require at least one block of additional padding,
costing 12 bytes. With this change, the only cost is 0-4 bytes at the
beginning of the heap to reach an initial 8-byte alignment.

See #98096

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60250709
@mysterymath mysterymath deleted the libc-malloc-align branch August 5, 2024 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants