Skip to content

IRGen: generate static arrays in read-only data sections. #59431

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 4 commits into from
Jun 17, 2022

Conversation

eeckstein
Copy link
Contributor

So far, static arrays had to be put into a writable section, because the isa pointer and the (immortal) ref count field were initialized dynamically at the first use of such an array.

But with a new runtime library, which exports the symbols for the (immortal) ref count field and the isa pointer, it's possible to put the whole array into a read-only section. I.e. make it a constant global.

Also, those array symbols get a new mangling to not mix it up with the old non-constant array symbols.

rdar://94185998

@eeckstein
Copy link
Contributor Author

@swift-ci test

@eeckstein
Copy link
Contributor Author

@swift-ci benchmark

Copy link
Contributor

@mikeash mikeash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really cool. I love me some good absolute address abuse.

// the metadata of the empty array buffer. The important thing is that its
// deinit is a no-op and does not actually destroy any elements.
__asm__(" .globl __swiftStaticArrayMetadata\n");
__asm__(".set __swiftStaticArrayMetadata, _$ss19__EmptyArrayStorageCN\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking this should become the real metadata symbol, and _$ss19__EmptyArrayStorageCN should be an alias to it. If we're expanding its use cases, then EmptyArrayStorage is no longer an accurate name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do this later. It would required renaming the EmptyArrayStorage class. I don't want to introduce too much churn here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable.

Copy link
Contributor

@Catfish-Man Catfish-Man left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only looked at the runtime bits, so please don't take this as a full approval, but looks great to me. Thank you for doing this!

@apple-fcloutier
Copy link

apple-fcloutier commented Jun 15, 2022

Big fan here. Would this make sense for other containers at the moment? I haven't checked how Set and Dictionary generate their initial state when used as let constants.

@eeckstein eeckstein force-pushed the read-only-static-arrays branch from b74d377 to 89a4907 Compare June 15, 2022 17:57
@eeckstein
Copy link
Contributor Author

@swift-ci test

@eeckstein
Copy link
Contributor Author

@apple-fcloutier Putting Set and Dictionary storages directly into read-only sections is much more complicated, unfortunately. What we do instead is to put set and dictionary literal-arrays into data sections and create the "real" Set/Dictionary from that at the first access.

@apple-fcloutier
Copy link

Thanks, I figured that might be the case. We'll take note of the limitation for now.

#error("unsupported pointer width")
#endif

// Static arrays can only contain trivial elements. Therefore we can reuse
Copy link
Contributor

@karwa karwa Jun 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the elements necessarily need to be trivial? Or is the important thing that their lifetimes are all statically known and don't need runtime refcounting? (I guess that is "trivial" - but trivial value as opposed to trivial type)

For example, would this work with an Array<Array<Int>> (assuming the inner arrays are also array literals)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, elements need to be trivial, i.e. must not contain any reference counted objects. One exception is String literals: String literals can be put into the data section, too (Note that String is not a trivial type).
Nested arrays are not supported. But we could support it in the future.

The layout of constant static arrays differs from non-constant static arrays.
Therefore use a different mangling to get symbol mismatches if for some reason two modules don't agree on which version a static array is.
Expands to, e.g. `x86_64-apple-macosx99.99`
This is useful to test features which are available in a "future" runtime.
* `__swiftImmortalRefCount`: The bit pattern of the ref-count field of immortal objects
* `__swiftStaticArrayMetadata`: The metadata used for static arrays.
So far, static arrays had to be put into a writable section, because the isa pointer and the (immortal) ref count field were initialized dynamically at the first use of such an array.

But with a new runtime library, which exports the symbols for the (immortal) ref count field and the isa pointer, it's possible to put the whole array into a read-only section. I.e. make it a constant global.

rdar://94185998
@eeckstein eeckstein force-pushed the read-only-static-arrays branch from 89a4907 to aca0d83 Compare June 17, 2022 09:22
@eeckstein
Copy link
Contributor Author

@swift-ci test

@eeckstein eeckstein merged commit b8804cd into swiftlang:main Jun 17, 2022
@eeckstein eeckstein deleted the read-only-static-arrays branch June 17, 2022 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants