Skip to content
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

Clean up boilerplate #432

Merged
merged 4 commits into from
Dec 21, 2023
Merged

Clean up boilerplate #432

merged 4 commits into from
Dec 21, 2023

Conversation

sjrd
Copy link
Contributor

@sjrd sjrd commented Dec 20, 2023

No description provided.

@sjrd sjrd requested a review from adpi2 December 20, 2023 16:20
We have a lot of methods whose results are cached using what is
essentially a thread-unsafe Context-dependent lazy val. We encode
the common shape of the initialization logic in an internal method
`Utils.memoized`.
`Symbols` have a number of fields that are set after their creation
by the readers. They must be set exactly once, and must be set
before they are read. We extract `assignOnce` and `getAssignedOnce`
to encode the boilerplate of that pattern.
We keep `withX` names for methods that return new instances without
changing the original.
inline def getAssignedOnce[A](value: A | Null)(inline msgIfNotAssignedYet: => String): A =
if value != null then value
else
// Extracted in a separate def for good jitting of the code calling `getAssignedOnce`
Copy link
Member

Choose a reason for hiding this comment

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

Is it because the JIT compiler won't compile the local def until it is called (which should rarely happen)?

Does it really make a difference?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's mostly that the regular getter remains small, under the limit that will always be inlined. The bytecode-long initialization path is extracted in a separate def. This is the same strategy that we use when compiling lazy vals. The getter does the cheap and short test whether it is already initialized, and if not it delegates to the lzy$compute method.

@sjrd sjrd merged commit 0a89f00 into scalacenter:main Dec 21, 2023
4 checks passed
@sjrd sjrd deleted the cleanup-boilerplate branch December 21, 2023 10:06
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.

2 participants