Skip to content

Base address of every empty array seems to be the same: issues where type alignment > word size #5599

Closed
swiftwasm/JavaScriptKit
#278
@ephemer

Description

@ephemer

Hi @kateinoigakukun,

Since Swift 6.0 (at the latest – I think we were previously using 5.7 with SwiftWasm) all empty arrays seem to point to the same base address.

A simpler reproducer is as follows:

    [Int]().withUnsafeBufferPointer { ptr in
        print(Int(bitPattern: ptr.baseAddress!)) // same
        print(Int(bitPattern: ptr.baseAddress!) % 8)
    }

    [Float]().withUnsafeBufferPointer { ptr in
        print(Int(bitPattern: ptr.baseAddress!)) // same
        print(Int(bitPattern: ptr.baseAddress!) % 8)
    }

    [Double]().withUnsafeBufferPointer { ptr in
        print(Int(bitPattern: ptr.baseAddress!)) // same
        print(Int(bitPattern: ptr.baseAddress!) % 8)
    }

The base address is always the same value in my testing (6.0.2 release SDK and toolchain) and is always indivisible by 8 (MemoryLayout<Double>.alignment).

In theory this is probably fine, but it breaks invariants in JavaScriptKit. Specifically, JSTypedArray([Double]()) passes the base address to new Float64Array, which cannot have a base address indivisible by 8. Double arrays that actually contain values do not have this issue, presumably because there the invariant is upheld by Swift itself (aligning the first value with a memory address divisible by MemoryLayout<Double>.alignment).

This behaviour does not seem to be unique to SwiftWasm (the base address also appears stable for all empty array types, even across multiple runs of a program), but on my machine the address is divisible by 8. I guess it's because my Mac is on arm64, meaning all pointers will be aligned to the word size of 8 bytes. I'm assuming on wasm (being a 32bit platform) all pointers, at the base level, are simply required to be aligned to the word length – that doesn't appear to be enough in all cases.

To work around this, it'd probably be enough to ensure the default address is aligned to 8 instead of 4, but I'm not sure of the implications of doing that otherwise.

We have run into this problem in a number of different cases, hindering our adoption of Swift 6 so far.

Do you have any ideas on how to fix this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions