webassembly: reuse JsProxy objects where possible and fix bug with lost references#18021
Merged
dpgeorge merged 4 commits intoSep 26, 2025
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #18021 +/- ##
=======================================
Coverage 98.38% 98.38%
=======================================
Files 171 171
Lines 22287 22287
=======================================
Hits 21928 21928
Misses 359 359 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Member
Author
|
@WebReflection FYI |
This test is not a PyProxy test, rather it's a JsProxy test. Signed-off-by: Damien George <damien@micropython.org>
Doing GC calls in the entry path (when JavaScript calls into MicroPython at the top/outer level) can lead to freeing of objects which are still in use. This is because the (JavaScript) objects are referenced in the input arguments to the C functions and they are not yet converted to full proxy objects and not yet tracked properly by the live-object tracker. Signed-off-by: Damien George <damien@micropython.org>
Commit ffa98cb improved equality for `JsProxy` objects so that, eg, `js.Object == js.Object` is true. As mentioned in micropython#17758, a further optimisation is to make identity work in that case, eg `js.Object is js.Object` should be true (on the Python side). This commit implements that, by keeping track of all `JsProxy` Python objects and reusing them where possible: where the underlying JS ref is equal, ie they point to the same JS object. That reduces memory churn and gives better identity behaviour of JS objects proxied over to Python. As part of this, a bug is fixed where JS objects can be freed while there's still a `JsProxy` referring to that JS object. A test is added for that exact scenario, and the test now passes. Signed-off-by: Damien George <damien@micropython.org>
With the parent commit implementing proper identities, this equality check option is no longer needed. Signed-off-by: Damien George <damien@micropython.org>
b4c4953 to
293bb0e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR #17758 improved equality for
JsProxyobjects so that, eg,js.Object == js.Objectis true.As mentioned in that PR, a further optimisation is to make identity work, eg
js.Object is js.Objectshould be true (on the Python side).This PR implements that, by keeping track of all
JsProxyPython objects and reusing them where possible (where the underlying JS ref is equal, ie they point to the same JS object). That reduces memory churn and gives better identity behaviour of JS objects proxied over to Python.As part of this, a bug is fixed where JS objects can be freed while there's still a
JsProxyreferring to that JS object. A test is added for that exact scenario, and the test now passes.Testing
Tested locally using the test suite. A new test is added to cover the bug (see above) and existing tests are updated to test object identity.
Trade-offs and Alternatives
This uses memory to keep track of all
JsProxyobjects, but that's probably counteracted by the fact that there are now lessJsProxyobjects lying around, due to reuse.Performance should be unchanged because the code was already checking for existing JS objects on the JS side. That information is now passed across to the Python side without any extra lookup overhead.