Skip to content

Pointer(T).malloc for strict alignments #14863

Open
@HertzDevil

Description

@HertzDevil

Crystal forwards Pointer(T).malloc to LibGC.malloc, LibGC.malloc_atomic, or LibC.malloc, which do not accept an alignment argument. C requires the pointer returned by malloc to be at least pointer-aligned; in practice, on 64-bit systems, all known C runtime implementations and Boehm GC allocate memory that is 16-byte-aligned. This has served us well so far because the strictest alignment we could obtain in Crystal code is also 16 bytes, but as soon as we impose anything stricter, e.g. due to #3057 or #7773, it would no longer be the case that Pointer(T).malloc returns a properly aligned pointer:

alias Float32x8 = ... # fits into an X86 YMM register
alignof(Float32x8)    # => 32

ptr = Pointer(Float32x8).malloc(16)
ptr.address % 32 # not necessarily zero
ptr[0]           # may segfault!

To make the above work, instead one should call GC_memalign, posix_memalign, or _aligned_malloc. Consequently there might also be public interfaces in GC that do the same for raw, untyped allocations as well. There are however major obstacles to this:

  • For implementing Pointer#realloc, only _aligned_realloc preserves the alignment of the allocated memory, and no such equivalents exist in the Boehm GC or the C runtime; LibGC.realloc and LibC.realloc will happily accept an overaligned pointer, but return a less strict one. That means an Array(Float32x8) should still perform misaligned pointer accesses once its buffer is resized. Presumably because of this, C++ does not require its allocators to implement reallocation, and resizing an std::vector in C++ is always done by malloc + memcpy + free.
  • GC_memalign always allocates non-atomic memory. There is some interest for supporting atomic memory as well in Provide global aligned allocators in gccpp library ivmai/bdwgc#547, since Boehm GC needs it for its own C++ wrappers.
  • Deallocation requires _aligned_free on MSVC, and the usual LibC.free will fail. (This only affects explicit uses of GC.free, however in the standard library it is exclusively used for setting memory functions in external C libraries, none of which expect any alignment parameters.)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions