-
-
Notifications
You must be signed in to change notification settings - Fork 881
avm2: Use return type of methods in optimizer #20257
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
base: master
Are you sure you want to change the base?
avm2: Use return type of methods in optimizer #20257
Conversation
1ae6596
to
0506f76
Compare
let my_name = instance_trait.name(); | ||
|
||
let names_match = super_name.local_name() == my_name.local_name() | ||
&& (super_name.namespace().matches_ns(my_name.namespace()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not do it during (or after) init_vtable
? It already contains the "check trait kind" logic. If we did it during init_vtable
, we could directly compare method_table[*disp_id as usize]
just before setting the override. If we did it after init_vtable
, we could lookup the name in resolved_traits
instead. Both feel faster and more correct than quadratic loop with name comparisons.
Actually...
I was just checking what FP does and turns out it does both: the trait kind check early and signature check late - and it can be observed.
The "is it legal to override trait kind A with B" and "overriding methods without override
is illegal" checks are done early during initial class loading, preparing the main name->property hashmap; FP does this eagerly, while we do init_vtable
late - so in FP the class can fail these even if it's never used.
(see Traits::getOverride
and where it's used. It does do a lookup on parent by name just like we do match resolved_traits.get()
in init_vtable
.)
Meanwhile the overridden methods' signatures are compared late, like in newclass
. So if the class exists and has a mismatched signature but is never used/referred to, there won't be any VerifyErrors.
(see TraitsBindings::checkOverride
, used in VTable::resolveSignatures(self)
, which is directly called from MethodEnv::newclass
(and a dozen other places). It also doesn't concern itself with names anymore, it just compares vtable.methods[dispid] vs parent_vtable.methods[dispid]).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not saying we need to do it exactly like FP; simply moving the entire logic during/after init_vtable
will just prevent some quadratic loops and should be conceptually simpler overall.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And even if the verification didn't move and stayed before init_vtable
, couldn't we still lookup the superclass's fields by name without a loop, just like init_vtable
does: resolved_traits.get(trait_data.name())
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "is it legal to override trait kind A with B" and "overriding methods without
override
is illegal" checks are done early during initial class loading, preparing the main name->property hashmap; FP does this eagerly, while we doinit_vtable
late - so in FP the class can fail these even if it's never used.(see
Traits::getOverride
and where it's used. It does do a lookup on parent by name just like we domatch resolved_traits.get()
ininit_vtable
.)Meanwhile the overridden methods' signatures are compared late, like in
newclass
. So if the class exists and has a mismatched signature but is never used/referred to, there won't be any VerifyErrors.
Currently I believe this PR exactly matches FP in this logic. If the signature comparison was done early (at Class creation time instead of ClassObject creation time) the referenced classes would not yet exist and we would get VerifyErrors.
I don't think it makes sense to move the whole verification to init_vtable
, as that is "just" meant to create the vtable from traits. For example, it takes a UC instead of an Activation and doesn't return any errors (at least as it is right now). I'll switch it to use resolved_traits.get
instead.
0506f76
to
e2dbf2c
Compare
Closes #17495
We now verify that overrides of methods use the same return type as the method they override, which allows us to make use of the return type of all methods in the optimizer.
Box2d stats: