Open osa1 opened 2 months ago
Summary: The issue is that TFA fails to inline the ==
call for a ByteBuffer
object, even though the object's type is known and the ==
operator is overridden. This results in a call to Object.==
instead of the optimized _I8ByteBuffer.==
method.
/cc @alexmarkov
Analyzing Object.==
calls in a typical application involves huge number of combinations of argument types and considerably slows down TFA, so those calls are eagerly approximated:
Does it make a big difference for dart2wasm? If so, we can probably add a configuration flag to TFA to enable analyzing those calls at the expense of higher compilation time. Still, I think it should be turned off for AOT (and maybe for dart2wasm) by default.
@alexmarkov It's not about analyzing the calls. It's about the fact that TFA has inferred a precise type for the receiver of the operator==
call, but hasn't annotated the EqualsCall
AST node with direct-call-metadata
.
Arguably a backend can get the inferred type for receiver and then re-resolve the ==
method from receiver class, but it would be nice if TFA could annotate it with direct call metadata as it does for all kinds of other calls.
@mkustermann Monomorphic target of a call is detected when the call site is analyzed. Arguments of operator ==
call are approximated with static types, so the call is not monomorphic and it is not devirtualized. Also note that eager approximation of arguments removes data flow link between result of Int8List.fromList([1, 2, 3]).buffer
and receiver of ==
call, so the inferred type of the receiver doesn't affect the call.
Does it make a big difference for dart2wasm?
I don't know how big the difference would be with this improved, but for the cases where ==
is just a type test + identical
of some field, right now we can't omit the type test and sometimes we also have to allocate intermediate objects.
When the use site is like x.buffer == y.buffer
, we can avoid allocating the byte buffers and then type tests in the ==
if we can inline ==
.
In this program, when compiling with dart2wasm, TFA infers the concrete type of
buffer1
, which has anoperator ==
override.Since the arguments to
==
are not nullable, we should be able to inline the==
call.However TFA currently does not add the
==
node to the direct call metadata, so we don't generate a direct call to the==
member.Relevant parts of the kernel after TFA:
Note that the inferred type of
buffer1
is_I8ByteBuffer
andbuffer2
is not nullable, but the==
call is toObject.==
, instead of_I8ByteBuffer.==
: https://github.com/dart-lang/sdk/blob/0e587759863d44984450246cae46ede3df5be541/sdk/lib/_internal/wasm/lib/typed_data.dart#L1113-L1115Compilation command:
Tried with the main branch at a5baf4e15b0.
cc @mkustermann