[swift-dev] statically initialized arrays
jgroff at apple.com
Mon Jun 19 11:58:33 CDT 2017
> On Jun 15, 2017, at 8:30 PM, Greg Parker via swift-dev <swift-dev at swift.org> wrote:
>> On Jun 15, 2017, at 4:39 PM, Andrew Trick via swift-dev <swift-dev at swift.org> wrote:
>>> On Jun 15, 2017, at 4:26 PM, Andrew Trick <atrick at apple.com> wrote:
>>>> On Jun 14, 2017, at 12:03 PM, Jordan Rose via swift-dev <swift-dev at swift.org> wrote:
>>>>> ad 3) IRGen support
>>>>> Generating statically initialized globals is already done today for structs and tuples.
>>>>> What’s needed is the handling of objects.
>>>>> In addition to creating the global itself, we also need a runtime call to initialize the object header. In other words: the object is statically initialized, except the header.
>>>>> HeapObject *swift::swift_initImmortalObject(HeapMetadata const *metadata, HeapObject *object)
>>>>> There are 2 reasons for that: first, the object header format is not part of the ABI. And second, in case of a bound generic type (e.g. array buffers) the metadata is not statically available.
>>>>> One way to call this runtime function is dynamically at the global_object instruction whenever the metadata pointer is still null (via swift_once).
>>>>> Another possibility would be to call it in a global constructor.
>>>>> If you have any feedback, please let me know
>>>> Please do not use a global constructor.
>>> What’s the objection to a global constructor about? We’re worried about dyld performance in this case?
>>>> Globals are already set up to handle one-time initialization; the fact that that initialization is now cheaper is still a good thing.
>>> These array literals aren’t Swift globals to begin with so I’m not sure what that means. Introducing a swift-once accessor everywhere they’re used means we can’t do the global optimizations that we normally do for globals with constant initializers. That might be the right choice but it would be good to understand why we’re making it.
>> Erik answered this. I forgot we need to initialize metadata. I agree we don’t want to do that in a global constructor. The fast path won’t go through swift-once, so the accessor will be just a bit of extra code size.
> swift_once is not the most efficient solution here - we don't need separate once token storage in this case - but it's fine for now. If necessary we can get rid of the once token requirement in a backwards-compatible way.
> (You can do without a separate token if (1) your storage is two pointers or less in size, (2) your storage is sufficiently well-aligned that it does not cross cache line boundaries, (3) your uninitialized value is zero, and (4) your initialized value is not zero. If all of these are true then you can perform the same trick that swift-once and dispatch-once use on the once token, but apply it directly to the data instead. And if your data is a single pointer you can do it faster than dispatch-once on weakly-ordered platforms that are not Alpha.)
Does the transition have to be strictly zero -> nonzero? I thought it just had to be "original value at the time page was mapped into process" -> "something else". For metadata initialization on 64-bit Apple, we could perhaps go from relative offset of metadata accessor function (which should always be <2GB in Mach-O) to absolute metadata address (which should always be >4GB on 64-bit Darwin).
More information about the swift-dev