Skip to content

Conversation

rr-codes
Copy link
Contributor

@rr-codes rr-codes commented Oct 5, 2025

3ecd1b1

[Swift in WebKit] The bmalloc module map is malformed (must include pas_lock.h)
https://bugs.webkit.org/show_bug.cgi?id=300198
rdar://161993222

Reviewed by Mark Lam.

Currently, (in Cocoa configurations at least) bmalloc depends on its client setting `OS_UNFAIR_LOCK_INLINE` to `1`;
otherwise, a compilation error happens. However, modules require that libraries/frameworks are usable without any
explicit configuration set. Therefore, bmalloc must at least be able to compile all its translation units regardless
of the value of `OS_UNFAIR_LOCK_INLINE`.

To workaround this, the `pas_lock.h` file was initially excluded from the module map. However, this is invalid as
it results in modular headers then including non-modular headers, which is a violation. This has not been a problem
so far because (a) there is no automatic module verification for libraries and (b) there is yet a Swift/Cxx interop
include path in WebKit or WebCore that depends on a file that uses `bmalloc`. Manually performing module verification
does reveal this issue, which is a violation and needs to be remedied.

To fix, the `#error` directive must be removed so that bmalloc can be built regardless of the value of `OS_UNFAIR_LOCK_INLINE`.
Consequently, some more compilation conditions have to be added to the file to account for configurations where
`OS_UNFAIR_LOCK_INLINE` is `0` since the relevant locking APIs from the system are unavailable.

In actuality, these paths where `OS_UNFAIR_LOCK_INLINE` is `0` will never actually be executed; they just need to
be able to compile.

Since this is technically a slight change of behavior, there are several safe guards added:

1. There are currently no Cocoa bmalloc clients that set `OS_UNFAIR_LOCK_INLINE` to `0` or leave it undefined
2. If, for some reason, one of the existing clients changed the value from `1` to `0`, a compiler diagnostic message
will be emitted with the same message as the error would have given.
3. The invalid branches are limited in scope, and immediately cause a release assertion if triggered.

One alternative considered was to wrap every header and translation unit in bmalloc with a compile time guard; this
was decided against because although this would technically not be a change in behavior for bmalloc, the changes would
be quite extensive and intrusive. Additionally, this would just move the issue up one dependency to the client of bmalloc anyways.

* Source/WebKit/Configurations/WebKit.xcconfig:
* Source/bmalloc/Configurations/module.modulemap:
* Source/bmalloc/libpas/src/libpas/pas_lock.h:
(pas_lock_lock):
(pas_lock_try_lock):
(pas_lock_unlock):

Canonical link: https://commits.webkit.org/301104@main

88c07de

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows Apple Internal
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe 🛠 win ✅ 🛠 ios-apple
✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug 🧪 wpe-wk2 🧪 win-tests ✅ 🛠 mac-apple
✅ 🧪 webkitperl 🧪 ios-wk2 ✅ 🧪 api-mac 🧪 api-wpe ❌ 🛠 vision-apple
🧪 ios-wk2-wpt ✅ 🧪 mac-wk1 ✅ 🛠 wpe-cairo
✅ 🛠 🧪 jsc 🧪 api-ios ✅ 🧪 mac-wk2 ✅ 🛠 gtk
✅ 🛠 🧪 jsc-arm64 ✅ 🛠 vision 🧪 mac-AS-debug-wk2 🧪 gtk-wk2
✅ 🛠 vision-sim ✅ 🧪 mac-wk2-stress 🧪 api-gtk
✅ 🛠 🧪 merge 🧪 vision-wk2 🧪 mac-intel-wk2 ✅ 🛠 playstation
✅ 🛠 tv ✅ 🛠 jsc-armv7
🛠 tv-sim 🧪 jsc-armv7-tests
🛠 watch
🛠 watch-sim

@rr-codes rr-codes requested review from a team and emw-apple as code owners October 5, 2025 17:25
@rr-codes rr-codes self-assigned this Oct 5, 2025
@rr-codes rr-codes added the WebKit Misc. For miscellaneous bugs in the WebKit framework (and not JavaScriptCore or WebCore). label Oct 5, 2025
@rr-codes rr-codes force-pushed the eng/Swift-in-WebKit-The-bmalloc-module-map-is-malformed-must-include-pas_lock-h branch from 57677d5 to 61ff0aa Compare October 5, 2025 17:30
os_unfair_lock_lock_with_options_inline(&lock->lock, options);
#else
PAS_UNUSED_PARAM(options);
PAS_ASSERT_NOT_REACHED();
Copy link
Contributor

Choose a reason for hiding this comment

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

When I originally put together the bmalloc modulemap, I assumed (perhaps incorrectly) that we needed to maintain the property of a compile-time failure if OS_UNFAIR_LOCK_INLINE was not defined. I'm glad if that's no longer the case...

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, that would be ideal, however it is impossible to maintain that while also having bmalloc be properly modularized that, so the solution described in a PR is a reasonable alternative.

pas_log("Thread %p Trylocking lock %p\n", pthread_self(), lock);
#if PAS_USE_ULOCK_SPI && (!defined(OS_UNFAIR_LOCK_INLINE) || !OS_UNFAIR_LOCK_INLINE)
result = false;
PAS_ASSERT_NOT_REACHED();
Copy link
Contributor

Choose a reason for hiding this comment

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

Your commit message says this is a release assert. PAS_ENABLE_ASSERT seems a bit more tricksy than that, it seems to depend on the platform. I assume you're aware, just checking.

Choose a reason for hiding this comment

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

Yes, Adrian is correct. Use this instead: PAS_ASSERT_IF(true, !"Should not be reached").

Copy link

@MenloDorian MenloDorian left a comment

Choose a reason for hiding this comment

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

r=me with the PAS_ASSERT_NOT_REACHED issue fixed.

@MenloDorian MenloDorian added the merging-blocked Applied to prevent a change from being merged label Oct 6, 2025
@rr-codes rr-codes removed the merging-blocked Applied to prevent a change from being merged label Oct 6, 2025
@rr-codes rr-codes force-pushed the eng/Swift-in-WebKit-The-bmalloc-module-map-is-malformed-must-include-pas_lock-h branch from 61ff0aa to d26cea3 Compare October 6, 2025 18:59
@rr-codes rr-codes added merge-queue Applied to send a pull request to merge-queue and removed merge-queue Applied to send a pull request to merge-queue labels Oct 6, 2025
@rr-codes rr-codes force-pushed the eng/Swift-in-WebKit-The-bmalloc-module-map-is-malformed-must-include-pas_lock-h branch from d26cea3 to 88c07de Compare October 7, 2025 00:36
@rr-codes rr-codes added the merge-queue Applied to send a pull request to merge-queue label Oct 7, 2025
…as_lock.h)

https://bugs.webkit.org/show_bug.cgi?id=300198
rdar://161993222

Reviewed by Mark Lam.

Currently, (in Cocoa configurations at least) bmalloc depends on its client setting `OS_UNFAIR_LOCK_INLINE` to `1`;
otherwise, a compilation error happens. However, modules require that libraries/frameworks are usable without any
explicit configuration set. Therefore, bmalloc must at least be able to compile all its translation units regardless
of the value of `OS_UNFAIR_LOCK_INLINE`.

To workaround this, the `pas_lock.h` file was initially excluded from the module map. However, this is invalid as
it results in modular headers then including non-modular headers, which is a violation. This has not been a problem
so far because (a) there is no automatic module verification for libraries and (b) there is yet a Swift/Cxx interop
include path in WebKit or WebCore that depends on a file that uses `bmalloc`. Manually performing module verification
does reveal this issue, which is a violation and needs to be remedied.

To fix, the `#error` directive must be removed so that bmalloc can be built regardless of the value of `OS_UNFAIR_LOCK_INLINE`.
Consequently, some more compilation conditions have to be added to the file to account for configurations where
`OS_UNFAIR_LOCK_INLINE` is `0` since the relevant locking APIs from the system are unavailable.

In actuality, these paths where `OS_UNFAIR_LOCK_INLINE` is `0` will never actually be executed; they just need to
be able to compile.

Since this is technically a slight change of behavior, there are several safe guards added:

1. There are currently no Cocoa bmalloc clients that set `OS_UNFAIR_LOCK_INLINE` to `0` or leave it undefined
2. If, for some reason, one of the existing clients changed the value from `1` to `0`, a compiler diagnostic message
will be emitted with the same message as the error would have given.
3. The invalid branches are limited in scope, and immediately cause a release assertion if triggered.

One alternative considered was to wrap every header and translation unit in bmalloc with a compile time guard; this
was decided against because although this would technically not be a change in behavior for bmalloc, the changes would
be quite extensive and intrusive. Additionally, this would just move the issue up one dependency to the client of bmalloc anyways.

* Source/WebKit/Configurations/WebKit.xcconfig:
* Source/bmalloc/Configurations/module.modulemap:
* Source/bmalloc/libpas/src/libpas/pas_lock.h:
(pas_lock_lock):
(pas_lock_try_lock):
(pas_lock_unlock):

Canonical link: https://commits.webkit.org/301104@main
@webkit-commit-queue webkit-commit-queue force-pushed the eng/Swift-in-WebKit-The-bmalloc-module-map-is-malformed-must-include-pas_lock-h branch from 88c07de to 3ecd1b1 Compare October 7, 2025 01:16
@webkit-commit-queue
Copy link
Collaborator

Committed 301104@main (3ecd1b1): https://commits.webkit.org/301104@main

Reviewed commits have been landed. Closing PR #51836 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit 3ecd1b1 into WebKit:main Oct 7, 2025
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Oct 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WebKit Misc. For miscellaneous bugs in the WebKit framework (and not JavaScriptCore or WebCore).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants