8000 Merge the itables into the corresponding vtables. by sjrd · Pull Request #5154 · scala-js/scala-js · GitHub
[go: up one dir, main page]

Skip to content

Merge the itables into the corresponding vtables. #5154

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 1 commit into from
Apr 9, 2025

Conversation

sjrd
Copy link
Member
@sjrd sjrd commented Apr 3, 2025

This is a trade-off on memory and code size.

The big advantage is that run-time instances of our classes use one fewer word each, since we do not have an itables field anymore. There could be some execution time improvements as a side effect, since we have one fewer word to initialize.

There are two disadvantages, but IMO they are comparatively minor:

  • We cannot use the "one empty itables to rule them all" trick anymore. Classes that implement no interfaces need to list their N null values. This has both a code size impact and a constant run-time memory cost.
  • We cannot share the itables of array classes either. This has no impact on code size (there is a single place in the code where we initialize those fields), but it does add run-time footprint to the vtables of each array type that gets created.

Interface method calls are not impacted, neither in the code we generate, nor in their run-time performance. Virtual method calls are only impacted insofar as the index of virtual method pointers is bumped up by the number of itable slots. This can add one more byte to some calls, due to the var-length encoding. If we get very unlucky, it could also push some vtable method pointers past a pre-fetch boundary, slowing down the calls at run-time. But I don't really think that's plausible.

Review by @gzm0 and @tanishiking.

@sjrd sjrd requested a review from gzm0 April 3, 2025 15:40
Copy link
Contributor
@gzm0 gzm0 left a comment

Choose a reason for hiding this comment

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

I agree with the design decision in this PR that runtime value memory footprint optimization is more important than type metadata memory footprint optimization.

(in a memory heavy program, I'd expect #values >> #types).

@@ -229,12 +228,14 @@ we get
```wat
(type $v.A (sub $v.java.lang.Object (struct
;; ... class metadata
;; ... itable slots
Copy link
Contributor

Choose a reason for hiding this comment

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

Just to check my understanding: The itable slots must be before the method dispatch references for the vtable subtyping relaionship to hold.

Copy link
Member Author
@sjrd sjrd Apr 6, 2025

Choose a reason for hiding this comment

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

Yes, that's right. It's stronger than the Wasm subtyping, though. Even if we were targeting native code, where subtyping is not a thing, we would have to do it this way. All classes have the same number of itable slots, but they have a different number of vtable method pointers. I we put method pointers first, either the itable slots would not be at a constant offset, or we would have to pad all method pointer tables to have the same (maximum) length.

Copy link
Contributor

Choose a reason for hiding this comment

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

One concern is that we might want to change an algorithm for compressing the itables to something that have different slots for classes (something like scala-native does scala-native/scala-native#4085). But we can just revert this change if it's a problem 👍

@sjrd sjrd force-pushed the fuse-itables-vtable branch from 4f2b39c to ce5577c Compare April 6, 2025 10:38
This is a trade-off on memory and code size.

The big advantage is that run-time instances of our classes use
one fewer word each, since we do not have an `itables` field
anymore. There could be some execution time improvements as a
side effect, since we have one fewer word to initialize.

There are two disadvantages, but IMO they are comparatively minor:

* We cannot use the "one empty itables to rule them all" trick
  anymore. Classes that implement no interfaces need to list their
  N `null` values. This has both a code size impact and a constant
  run-time memory cost.
* We cannot share the itables of array classes either. This has no
  impact on code size (there is a single place in the code where
  we initialize those fields), but it does add run-time footprint
  to the vtables of each array type that gets created.

Interface method calls are not impacted, neither in the code we
generate, nor in their run-time performance. Virtual method calls
are only impacted insofar as the index of virtual method pointers
is bumped up by the number of itable slots. This can add one more
byte to some calls, due to the var-length encoding. If we get very
unlucky, it could also push some vtable method pointers past a
pre-fetch boundary, slowing down the calls at run-time. But I
don't really think that's plausible.
@sjrd sjrd force-pushed the fuse-itables-vtable branch from ce5577c to 1b989f2 Compare April 6, 2025 21:10
@@ -229,12 +228,14 @@ we get
```wat
(type $v.A (sub $v.java.lang.Object (struct
;; ... class metadata
;; ... itable slots
Copy link
Contributor

Choose a reason for hiding this comment

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

One concern is that we might want to change an algorithm for compressing the itables to something that have different slots for classes (something like scala-native does scala-native/scala-native#4085). But we can just revert this change if it's a problem 👍

@sjrd sjrd merged commit e507300 into scala-js:main Apr 9, 2025
3 checks passed
@sjrd sjrd deleted the fuse-itables-vtable branch April 9, 2025 02:57
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.

3 participants
0